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 android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.content.pm.PackageManager; 25 import android.net.IpConfiguration; 26 import android.net.IpConfiguration.ProxySettings; 27 import android.net.MacAddress; 28 import android.net.NetworkSpecifier; 29 import android.net.ProxyInfo; 30 import android.net.StaticIpConfiguration; 31 import android.net.Uri; 32 import android.net.util.MacAddressUtils; 33 import android.os.Build; 34 import android.os.Parcel; 35 import android.os.Parcelable; 36 import android.os.SystemClock; 37 import android.os.UserHandle; 38 import android.telephony.TelephonyManager; 39 import android.text.TextUtils; 40 import android.util.Log; 41 import android.util.SparseArray; 42 43 import com.android.internal.annotations.VisibleForTesting; 44 45 import java.lang.annotation.Retention; 46 import java.lang.annotation.RetentionPolicy; 47 import java.util.Arrays; 48 import java.util.BitSet; 49 import java.util.Calendar; 50 import java.util.HashMap; 51 52 /** 53 * A class representing a configured Wi-Fi network, including the 54 * security configuration. 55 * 56 * @deprecated Use {@link WifiNetworkSpecifier.Builder} to create {@link NetworkSpecifier} and 57 * {@link WifiNetworkSuggestion.Builder} to create {@link WifiNetworkSuggestion}. This will become a 58 * system use only object in the future. 59 */ 60 @Deprecated 61 public class WifiConfiguration implements Parcelable { 62 private static final String TAG = "WifiConfiguration"; 63 /** 64 * Current Version of the Backup Serializer. 65 */ 66 private static final int BACKUP_VERSION = 3; 67 /** {@hide} */ 68 public static final String ssidVarName = "ssid"; 69 /** {@hide} */ 70 public static final String bssidVarName = "bssid"; 71 /** {@hide} */ 72 public static final String pskVarName = "psk"; 73 /** {@hide} */ 74 @Deprecated 75 @UnsupportedAppUsage 76 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 77 /** {@hide} */ 78 @Deprecated 79 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 80 /** {@hide} */ 81 public static final String priorityVarName = "priority"; 82 /** {@hide} */ 83 public static final String hiddenSSIDVarName = "scan_ssid"; 84 /** {@hide} */ 85 public static final String pmfVarName = "ieee80211w"; 86 /** {@hide} */ 87 public static final String updateIdentiferVarName = "update_identifier"; 88 /** 89 * The network ID for an invalid network. 90 * 91 * @hide 92 */ 93 @SystemApi 94 public static final int INVALID_NETWORK_ID = -1; 95 /** {@hide} */ 96 public static final int LOCAL_ONLY_NETWORK_ID = -2; 97 98 /** {@hide} */ 99 private String mPasspointManagementObjectTree; 100 /** {@hide} */ 101 private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3; 102 103 /** 104 * Recognized key management schemes. 105 */ 106 public static class KeyMgmt { KeyMgmt()107 private KeyMgmt() { } 108 109 /** @hide */ 110 @Retention(RetentionPolicy.SOURCE) 111 @IntDef(value = { 112 NONE, 113 WPA_PSK, 114 WPA_EAP, 115 IEEE8021X, 116 WPA2_PSK, 117 OSEN, 118 FT_PSK, 119 FT_EAP, 120 SAE, 121 OWE, 122 SUITE_B_192, 123 WPA_PSK_SHA256, 124 WPA_EAP_SHA256, 125 WAPI_PSK, 126 WAPI_CERT, 127 FILS_SHA256, 128 FILS_SHA384}) 129 public @interface KeyMgmtScheme {} 130 131 /** WPA is not used; plaintext or static WEP could be used. */ 132 public static final int NONE = 0; 133 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 134 public static final int WPA_PSK = 1; 135 /** WPA using EAP authentication. Generally used with an external authentication server. */ 136 public static final int WPA_EAP = 2; 137 /** 138 * IEEE 802.1X using EAP authentication and (optionally) dynamically 139 * generated WEP keys. 140 */ 141 public static final int IEEE8021X = 3; 142 143 /** 144 * WPA2 pre-shared key for use with soft access point 145 * (requires {@code preSharedKey} to be specified). 146 * @hide 147 */ 148 @SystemApi 149 public static final int WPA2_PSK = 4; 150 /** 151 * Hotspot 2.0 r2 OSEN: 152 * @hide 153 */ 154 public static final int OSEN = 5; 155 156 /** 157 * IEEE 802.11r Fast BSS Transition with PSK authentication. 158 * @hide 159 */ 160 public static final int FT_PSK = 6; 161 162 /** 163 * IEEE 802.11r Fast BSS Transition with EAP authentication. 164 * @hide 165 */ 166 public static final int FT_EAP = 7; 167 168 /** 169 * Simultaneous Authentication of Equals 170 */ 171 public static final int SAE = 8; 172 173 /** 174 * Opportunististic Wireless Encryption 175 */ 176 public static final int OWE = 9; 177 178 /** 179 * SUITE_B_192 192 bit level 180 */ 181 public static final int SUITE_B_192 = 10; 182 183 /** 184 * WPA pre-shared key with stronger SHA256-based algorithms. 185 * @hide 186 */ 187 public static final int WPA_PSK_SHA256 = 11; 188 189 /** 190 * WPA using EAP authentication with stronger SHA256-based algorithms. 191 * @hide 192 */ 193 public static final int WPA_EAP_SHA256 = 12; 194 195 /** 196 * WAPI pre-shared key (requires {@code preSharedKey} to be specified). 197 * @hide 198 */ 199 @SystemApi 200 public static final int WAPI_PSK = 13; 201 202 /** 203 * WAPI certificate to be specified. 204 * @hide 205 */ 206 @SystemApi 207 public static final int WAPI_CERT = 14; 208 209 /** 210 * IEEE 802.11ai FILS SK with SHA256 211 * @hide 212 */ 213 public static final int FILS_SHA256 = 15; 214 /** 215 * IEEE 802.11ai FILS SK with SHA384: 216 * @hide 217 */ 218 public static final int FILS_SHA384 = 16; 219 220 public static final String varName = "key_mgmt"; 221 222 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", 223 "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP", 224 "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256", 225 "WAPI_PSK", "WAPI_CERT", "FILS_SHA256", "FILS_SHA384" }; 226 } 227 228 /** 229 * Recognized security protocols. 230 */ 231 public static class Protocol { Protocol()232 private Protocol() { } 233 234 /** WPA/IEEE 802.11i/D3.0 235 * @deprecated Due to security and performance limitations, use of WPA-1 networks 236 * is discouraged. WPA-2 (RSN) should be used instead. */ 237 @Deprecated 238 public static final int WPA = 0; 239 /** RSN WPA2/WPA3/IEEE 802.11i */ 240 public static final int RSN = 1; 241 /** HS2.0 r2 OSEN 242 * @hide 243 */ 244 public static final int OSEN = 2; 245 246 /** 247 * WAPI Protocol 248 */ 249 public static final int WAPI = 3; 250 251 public static final String varName = "proto"; 252 253 public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" }; 254 } 255 256 /** 257 * Recognized IEEE 802.11 authentication algorithms. 258 */ 259 public static class AuthAlgorithm { AuthAlgorithm()260 private AuthAlgorithm() { } 261 262 /** Open System authentication (required for WPA/WPA2) */ 263 public static final int OPEN = 0; 264 /** Shared Key authentication (requires static WEP keys) 265 * @deprecated Due to security and performance limitations, use of WEP networks 266 * is discouraged. */ 267 @Deprecated 268 public static final int SHARED = 1; 269 /** LEAP/Network EAP (only used with LEAP) */ 270 public static final int LEAP = 2; 271 272 /** SAE (Used only for WPA3-Personal) */ 273 public static final int SAE = 3; 274 275 public static final String varName = "auth_alg"; 276 277 public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" }; 278 } 279 280 /** 281 * Recognized pairwise ciphers for WPA. 282 */ 283 public static class PairwiseCipher { PairwiseCipher()284 private PairwiseCipher() { } 285 286 /** Use only Group keys (deprecated) */ 287 public static final int NONE = 0; 288 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 289 * @deprecated Due to security and performance limitations, use of WPA-1 networks 290 * is discouraged. WPA-2 (RSN) should be used instead. */ 291 @Deprecated 292 public static final int TKIP = 1; 293 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 294 public static final int CCMP = 2; 295 /** 296 * AES in Galois/Counter Mode 297 */ 298 public static final int GCMP_256 = 3; 299 /** 300 * SMS4 cipher for WAPI 301 */ 302 public static final int SMS4 = 4; 303 304 public static final String varName = "pairwise"; 305 306 public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4" }; 307 } 308 309 /** 310 * Recognized group ciphers. 311 * <pre> 312 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 313 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 314 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 315 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 316 * GCMP_256 = AES in Galois/Counter Mode 317 * </pre> 318 */ 319 public static class GroupCipher { GroupCipher()320 private GroupCipher() { } 321 322 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 323 * @deprecated Due to security and performance limitations, use of WEP networks 324 * is discouraged. */ 325 @Deprecated 326 public static final int WEP40 = 0; 327 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 328 * @deprecated Due to security and performance limitations, use of WEP networks 329 * is discouraged. */ 330 @Deprecated 331 public static final int WEP104 = 1; 332 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 333 public static final int TKIP = 2; 334 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 335 public static final int CCMP = 3; 336 /** Hotspot 2.0 r2 OSEN 337 * @hide 338 */ 339 public static final int GTK_NOT_USED = 4; 340 /** 341 * AES in Galois/Counter Mode 342 */ 343 public static final int GCMP_256 = 5; 344 /** 345 * SMS4 cipher for WAPI 346 */ 347 public static final int SMS4 = 6; 348 349 public static final String varName = "group"; 350 351 public static final String[] strings = 352 { /* deprecated */ "WEP40", /* deprecated */ "WEP104", 353 "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256", 354 "SMS4" }; 355 } 356 357 /** 358 * Recognized group management ciphers. 359 * <pre> 360 * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits 361 * BIP_GMAC_128 = Galois Message Authentication Code 128 bits 362 * BIP_GMAC_256 = Galois Message Authentication Code 256 bits 363 * </pre> 364 */ 365 public static class GroupMgmtCipher { GroupMgmtCipher()366 private GroupMgmtCipher() { } 367 368 /** CMAC-256 = Cipher-based Message Authentication Code */ 369 public static final int BIP_CMAC_256 = 0; 370 371 /** GMAC-128 = Galois Message Authentication Code */ 372 public static final int BIP_GMAC_128 = 1; 373 374 /** GMAC-256 = Galois Message Authentication Code */ 375 public static final int BIP_GMAC_256 = 2; 376 377 private static final String varName = "groupMgmt"; 378 379 private static final String[] strings = { "BIP_CMAC_256", 380 "BIP_GMAC_128", "BIP_GMAC_256"}; 381 } 382 383 /** 384 * Recognized suiteB ciphers. 385 * <pre> 386 * ECDHE_ECDSA 387 * ECDHE_RSA 388 * </pre> 389 * @hide 390 */ 391 public static class SuiteBCipher { SuiteBCipher()392 private SuiteBCipher() { } 393 394 /** Diffie-Hellman with Elliptic Curve_ECDSA signature */ 395 public static final int ECDHE_ECDSA = 0; 396 397 /** Diffie-Hellman with_RSA signature */ 398 public static final int ECDHE_RSA = 1; 399 400 private static final String varName = "SuiteB"; 401 402 private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; 403 } 404 405 /** Possible status of a network configuration. */ 406 public static class Status { Status()407 private Status() { } 408 409 /** this is the network we are currently connected to */ 410 public static final int CURRENT = 0; 411 /** supplicant will not attempt to use this network */ 412 public static final int DISABLED = 1; 413 /** supplicant will consider this network available for association */ 414 public static final int ENABLED = 2; 415 416 public static final String[] strings = { "current", "disabled", "enabled" }; 417 } 418 419 /** Security type for an open network. */ 420 public static final int SECURITY_TYPE_OPEN = 0; 421 /** Security type for a WEP network. */ 422 public static final int SECURITY_TYPE_WEP = 1; 423 /** Security type for a PSK network. */ 424 public static final int SECURITY_TYPE_PSK = 2; 425 /** Security type for an EAP network. */ 426 public static final int SECURITY_TYPE_EAP = 3; 427 /** Security type for an SAE network. */ 428 public static final int SECURITY_TYPE_SAE = 4; 429 /** Security type for an EAP Suite B network. */ 430 public static final int SECURITY_TYPE_EAP_SUITE_B = 5; 431 /** Security type for an OWE network. */ 432 public static final int SECURITY_TYPE_OWE = 6; 433 /** Security type for a WAPI PSK network. */ 434 public static final int SECURITY_TYPE_WAPI_PSK = 7; 435 /** Security type for a WAPI Certificate network. */ 436 public static final int SECURITY_TYPE_WAPI_CERT = 8; 437 438 /** 439 * Security types we support. 440 * @hide 441 */ 442 @Retention(RetentionPolicy.SOURCE) 443 @IntDef(prefix = { "SECURITY_TYPE_" }, value = { 444 SECURITY_TYPE_OPEN, 445 SECURITY_TYPE_WEP, 446 SECURITY_TYPE_PSK, 447 SECURITY_TYPE_EAP, 448 SECURITY_TYPE_SAE, 449 SECURITY_TYPE_EAP_SUITE_B, 450 SECURITY_TYPE_OWE, 451 SECURITY_TYPE_WAPI_PSK, 452 SECURITY_TYPE_WAPI_CERT 453 }) 454 public @interface SecurityType {} 455 456 /** 457 * Set the various security params to correspond to the provided security type. 458 * This is accomplished by setting the various BitSets exposed in WifiConfiguration. 459 * 460 * @param securityType One of the following security types: 461 * {@link #SECURITY_TYPE_OPEN}, 462 * {@link #SECURITY_TYPE_WEP}, 463 * {@link #SECURITY_TYPE_PSK}, 464 * {@link #SECURITY_TYPE_EAP}, 465 * {@link #SECURITY_TYPE_SAE}, 466 * {@link #SECURITY_TYPE_EAP_SUITE_B}, 467 * {@link #SECURITY_TYPE_OWE}, 468 * {@link #SECURITY_TYPE_WAPI_PSK}, or 469 * {@link #SECURITY_TYPE_WAPI_CERT} 470 */ setSecurityParams(@ecurityType int securityType)471 public void setSecurityParams(@SecurityType int securityType) { 472 // Clear all the bitsets. 473 allowedKeyManagement.clear(); 474 allowedProtocols.clear(); 475 allowedAuthAlgorithms.clear(); 476 allowedPairwiseCiphers.clear(); 477 allowedGroupCiphers.clear(); 478 allowedGroupManagementCiphers.clear(); 479 allowedSuiteBCiphers.clear(); 480 481 switch (securityType) { 482 case SECURITY_TYPE_OPEN: 483 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 484 break; 485 case SECURITY_TYPE_WEP: 486 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 487 allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); 488 allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); 489 break; 490 case SECURITY_TYPE_PSK: 491 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 492 break; 493 case SECURITY_TYPE_EAP: 494 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); 495 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); 496 break; 497 case SECURITY_TYPE_SAE: 498 allowedProtocols.set(WifiConfiguration.Protocol.RSN); 499 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); 500 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); 501 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); 502 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); 503 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); 504 requirePmf = true; 505 break; 506 case SECURITY_TYPE_EAP_SUITE_B: 507 allowedProtocols.set(WifiConfiguration.Protocol.RSN); 508 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); 509 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); 510 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); 511 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); 512 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); 513 allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); 514 // Note: allowedSuiteBCiphers bitset will be set by the service once the 515 // certificates are attached to this profile 516 requirePmf = true; 517 break; 518 case SECURITY_TYPE_OWE: 519 allowedProtocols.set(WifiConfiguration.Protocol.RSN); 520 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); 521 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); 522 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); 523 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); 524 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); 525 requirePmf = true; 526 break; 527 case SECURITY_TYPE_WAPI_PSK: 528 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); 529 allowedProtocols.set(WifiConfiguration.Protocol.WAPI); 530 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); 531 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); 532 break; 533 case SECURITY_TYPE_WAPI_CERT: 534 allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); 535 allowedProtocols.set(WifiConfiguration.Protocol.WAPI); 536 allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); 537 allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); 538 break; 539 default: 540 throw new IllegalArgumentException("unknown security type " + securityType); 541 } 542 } 543 544 /** @hide */ 545 public static final int UNKNOWN_UID = -1; 546 547 /** 548 * The ID number that the supplicant uses to identify this 549 * network configuration entry. This must be passed as an argument 550 * to most calls into the supplicant. 551 */ 552 public int networkId; 553 554 // Fixme We need remove this field to use only Quality network selection status only 555 /** 556 * The current status of this network configuration entry. 557 * @see Status 558 */ 559 public int status; 560 561 /** 562 * The network's SSID. Can either be a UTF-8 string, 563 * which must be enclosed in double quotation marks 564 * (e.g., {@code "MyNetwork"}), or a string of 565 * hex digits, which are not enclosed in quotes 566 * (e.g., {@code 01a243f405}). 567 */ 568 public String SSID; 569 570 /** 571 * When set, this network configuration entry should only be used when 572 * associating with the AP having the specified BSSID. The value is 573 * a string in the format of an Ethernet MAC address, e.g., 574 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 575 */ 576 public String BSSID; 577 578 /** @hide */ 579 @Retention(RetentionPolicy.SOURCE) 580 @IntDef(prefix = {"AP_BAND_"}, value = { 581 AP_BAND_2GHZ, 582 AP_BAND_5GHZ, 583 AP_BAND_ANY}) 584 public @interface ApBand {} 585 586 /** 587 * 2GHz band. 588 * @hide 589 */ 590 public static final int AP_BAND_2GHZ = 0; 591 592 /** 593 * 5GHz band. 594 * @hide 595 */ 596 public static final int AP_BAND_5GHZ = 1; 597 598 /** 599 * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability, 600 * operating country code and current radio conditions. 601 * @hide 602 */ 603 public static final int AP_BAND_ANY = -1; 604 605 /** 606 * The band which the AP resides on. 607 * One of {@link #AP_BAND_2GHZ}, {@link #AP_BAND_5GHZ}, or {@link #AP_BAND_ANY}. 608 * By default, {@link #AP_BAND_2GHZ} is chosen. 609 * 610 * @hide 611 */ 612 @UnsupportedAppUsage 613 @ApBand 614 public int apBand = AP_BAND_2GHZ; 615 616 /** 617 * The channel which AP resides on,currently, US only 618 * 2G 1-11 619 * 5G 36,40,44,48,149,153,157,161,165 620 * 0 - find a random available channel according to the apBand 621 * @hide 622 */ 623 @UnsupportedAppUsage 624 public int apChannel = 0; 625 626 /** 627 * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in 628 * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or 629 * a string of 64 hex digits for raw PSK. 630 * <p/> 631 * When the value of this key is read, the actual key is 632 * not returned, just a "*" if the key has a value, or the null 633 * string otherwise. 634 */ 635 public String preSharedKey; 636 637 /** 638 * Four WEP keys. For each of the four values, provide either an ASCII 639 * string enclosed in double quotation marks (e.g., {@code "abcdef"}), 640 * a string of hex digits (e.g., {@code 0102030405}), or an empty string 641 * (e.g., {@code ""}). 642 * <p/> 643 * When the value of one of these keys is read, the actual key is 644 * not returned, just a "*" if the key has a value, or the null 645 * string otherwise. 646 * @deprecated Due to security and performance limitations, use of WEP networks 647 * is discouraged. 648 */ 649 @Deprecated 650 public String[] wepKeys; 651 652 /** Default WEP key index, ranging from 0 to 3. 653 * @deprecated Due to security and performance limitations, use of WEP networks 654 * is discouraged. */ 655 @Deprecated 656 public int wepTxKeyIndex; 657 658 /** 659 * Priority determines the preference given to a network by {@code wpa_supplicant} 660 * when choosing an access point with which to associate. 661 * @deprecated This field does not exist anymore. 662 */ 663 @Deprecated 664 public int priority; 665 666 /** 667 * This is a network that does not broadcast its SSID, so an 668 * SSID-specific probe request must be used for scans. 669 */ 670 public boolean hiddenSSID; 671 672 /** 673 * True if the network requires Protected Management Frames (PMF), false otherwise. 674 * @hide 675 */ 676 @SystemApi 677 public boolean requirePmf; 678 679 /** 680 * Update identifier, for Passpoint network. 681 * @hide 682 */ 683 public String updateIdentifier; 684 685 /** 686 * The set of key management protocols supported by this configuration. 687 * See {@link KeyMgmt} for descriptions of the values. 688 * Defaults to WPA-PSK WPA-EAP. 689 */ 690 @NonNull 691 public BitSet allowedKeyManagement; 692 /** 693 * The set of security protocols supported by this configuration. 694 * See {@link Protocol} for descriptions of the values. 695 * Defaults to WPA RSN. 696 */ 697 @NonNull 698 public BitSet allowedProtocols; 699 /** 700 * The set of authentication protocols supported by this configuration. 701 * See {@link AuthAlgorithm} for descriptions of the values. 702 * Defaults to automatic selection. 703 */ 704 @NonNull 705 public BitSet allowedAuthAlgorithms; 706 /** 707 * The set of pairwise ciphers for WPA supported by this configuration. 708 * See {@link PairwiseCipher} for descriptions of the values. 709 * Defaults to CCMP TKIP. 710 */ 711 @NonNull 712 public BitSet allowedPairwiseCiphers; 713 /** 714 * The set of group ciphers supported by this configuration. 715 * See {@link GroupCipher} for descriptions of the values. 716 * Defaults to CCMP TKIP WEP104 WEP40. 717 */ 718 @NonNull 719 public BitSet allowedGroupCiphers; 720 /** 721 * The set of group management ciphers supported by this configuration. 722 * See {@link GroupMgmtCipher} for descriptions of the values. 723 */ 724 @NonNull 725 public BitSet allowedGroupManagementCiphers; 726 /** 727 * The set of SuiteB ciphers supported by this configuration. 728 * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the 729 * certificate type that is used in this configuration. 730 */ 731 @NonNull 732 public BitSet allowedSuiteBCiphers; 733 /** 734 * The enterprise configuration details specifying the EAP method, 735 * certificates and other settings associated with the EAP. 736 */ 737 public WifiEnterpriseConfig enterpriseConfig; 738 739 /** 740 * Fully qualified domain name of a Passpoint configuration 741 */ 742 public String FQDN; 743 744 /** 745 * Name of Passpoint credential provider 746 */ 747 public String providerFriendlyName; 748 749 /** 750 * Flag indicating if this network is provided by a home Passpoint provider or a roaming 751 * Passpoint provider. This flag will be {@code true} if this network is provided by 752 * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider 753 * or is a non-Passpoint network. 754 */ 755 public boolean isHomeProviderNetwork; 756 757 /** 758 * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where 759 * Passpoint credential will be considered valid 760 */ 761 public long[] roamingConsortiumIds; 762 763 /** 764 * True if this network configuration is visible to and usable by other users on the 765 * same device, false otherwise. 766 * 767 * @hide 768 */ 769 @SystemApi 770 public boolean shared; 771 772 /** 773 * @hide 774 */ 775 @NonNull 776 @UnsupportedAppUsage 777 private IpConfiguration mIpConfiguration; 778 779 /** 780 * @hide 781 * dhcp server MAC address if known 782 */ 783 public String dhcpServer; 784 785 /** 786 * @hide 787 * default Gateway MAC address if known 788 */ 789 @UnsupportedAppUsage 790 public String defaultGwMacAddress; 791 792 /** 793 * @hide 794 * last time we connected, this configuration had validated internet access 795 */ 796 @UnsupportedAppUsage 797 public boolean validatedInternetAccess; 798 799 /** 800 * @hide 801 * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM) 802 * This value is populated from scan results that contain Beacon Frames, which are infrequent. 803 * The value is not guaranteed to be set or current (Although it SHOULDNT change once set) 804 * Valid values are from 1 - 255. Initialized here as 0, use this to check if set. 805 */ 806 public int dtimInterval = 0; 807 808 /** 809 * Flag indicating if this configuration represents a legacy Passpoint configuration 810 * (Release N or older). This is used for migrating Passpoint configuration from N to O. 811 * This will no longer be needed after O. 812 * @hide 813 */ 814 public boolean isLegacyPasspointConfig = false; 815 /** 816 * @hide 817 * Uid of app creating the configuration 818 */ 819 @SystemApi 820 public int creatorUid; 821 822 /** 823 * @hide 824 * Uid of last app issuing a connection related command 825 */ 826 @UnsupportedAppUsage 827 public int lastConnectUid; 828 829 /** 830 * @hide 831 * Uid of last app modifying the configuration 832 */ 833 @SystemApi 834 public int lastUpdateUid; 835 836 /** 837 * @hide 838 * Universal name for app creating the configuration 839 * see {@link PackageManager#getNameForUid(int)} 840 */ 841 @SystemApi 842 public String creatorName; 843 844 /** 845 * @hide 846 * Universal name for app updating the configuration 847 * see {@link PackageManager#getNameForUid(int)} 848 */ 849 @SystemApi 850 public String lastUpdateName; 851 852 /** 853 * The carrier ID identifies the operator who provides this network configuration. 854 * see {@link TelephonyManager#getSimCarrierId()} 855 * @hide 856 */ 857 @SystemApi 858 public int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 859 860 /** 861 * @hide 862 * Auto-join is allowed by user for this network. 863 * Default true. 864 */ 865 @SystemApi 866 public boolean allowAutojoin = true; 867 868 /** @hide **/ 869 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 870 public static int INVALID_RSSI = -127; 871 872 /** 873 * @hide 874 * Number of reports indicating no Internet Access 875 */ 876 @UnsupportedAppUsage 877 public int numNoInternetAccessReports; 878 879 /** 880 * @hide 881 * The WiFi configuration is considered to have no internet access for purpose of autojoining 882 * if there has been a report of it having no internet access, and, it never have had 883 * internet access in the past. 884 */ 885 @SystemApi hasNoInternetAccess()886 public boolean hasNoInternetAccess() { 887 return numNoInternetAccessReports > 0 && !validatedInternetAccess; 888 } 889 890 /** 891 * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a 892 * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to 893 * this configuration and selects "don't ask again". 894 * @hide 895 */ 896 @UnsupportedAppUsage 897 public boolean noInternetAccessExpected; 898 899 /** 900 * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a 901 * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to 902 * this configuration and selects "don't ask again". 903 * @hide 904 */ 905 @SystemApi isNoInternetAccessExpected()906 public boolean isNoInternetAccessExpected() { 907 return noInternetAccessExpected; 908 } 909 910 /** 911 * This Wifi configuration is expected for OSU(Online Sign Up) of Passpoint Release 2. 912 * @hide 913 */ 914 public boolean osu; 915 916 /** 917 * @hide 918 * Last time the system was connected to this configuration. 919 */ 920 public long lastConnected; 921 922 /** 923 * @hide 924 * Last time the system was disconnected to this configuration. 925 */ 926 public long lastDisconnected; 927 928 /** 929 * Set if the configuration was self added by the framework 930 * This boolean is cleared if we get a connect/save/ update or 931 * any wifiManager command that indicate the user interacted with the configuration 932 * since we will now consider that the configuration belong to him. 933 * @deprecated only kept for @UnsupportedAppUsage 934 * @hide 935 */ 936 @UnsupportedAppUsage 937 public boolean selfAdded; 938 939 /** 940 * Peer WifiConfiguration this WifiConfiguration was added for 941 * @hide 942 */ 943 public String peerWifiConfiguration; 944 945 /** 946 * @hide 947 * Indicate that a WifiConfiguration is temporary and should not be saved 948 * nor considered by AutoJoin. 949 */ 950 public boolean ephemeral; 951 952 /** 953 * @hide 954 * Indicate that a WifiConfiguration is temporary and should not be saved 955 * nor considered by AutoJoin. 956 */ 957 @SystemApi isEphemeral()958 public boolean isEphemeral() { 959 return ephemeral; 960 } 961 962 /** 963 * Indicate whether the network is trusted or not. Networks are considered trusted 964 * if the user explicitly allowed this network connection. 965 * This bit can be used by suggestion network, see 966 * {@link WifiNetworkSuggestion.Builder#setUntrusted(boolean)} 967 * @hide 968 */ 969 public boolean trusted; 970 971 /** 972 * True if this Wifi configuration is created from a {@link WifiNetworkSuggestion}, 973 * false otherwise. 974 * 975 * @hide 976 */ 977 @SystemApi 978 public boolean fromWifiNetworkSuggestion; 979 980 /** 981 * True if this Wifi configuration is created from a {@link WifiNetworkSpecifier}, 982 * false otherwise. 983 * 984 * @hide 985 */ 986 @SystemApi 987 public boolean fromWifiNetworkSpecifier; 988 989 /** 990 * True if the creator of this configuration has expressed that it 991 * should be considered metered, false otherwise. 992 * 993 * @see #isMetered(WifiConfiguration, WifiInfo) 994 * 995 * @hide 996 */ 997 @SystemApi 998 public boolean meteredHint; 999 1000 /** @hide */ 1001 @Retention(RetentionPolicy.SOURCE) 1002 @IntDef(prefix = {"METERED_OVERRIDE_"}, value = { 1003 METERED_OVERRIDE_NONE, 1004 METERED_OVERRIDE_METERED, 1005 METERED_OVERRIDE_NOT_METERED}) 1006 public @interface MeteredOverride {} 1007 1008 /** 1009 * No metered override. 1010 * @hide 1011 */ 1012 @SystemApi 1013 public static final int METERED_OVERRIDE_NONE = 0; 1014 /** 1015 * Override network to be metered. 1016 * @hide 1017 */ 1018 @SystemApi 1019 public static final int METERED_OVERRIDE_METERED = 1; 1020 /** 1021 * Override network to be unmetered. 1022 * @hide 1023 */ 1024 @SystemApi 1025 public static final int METERED_OVERRIDE_NOT_METERED = 2; 1026 1027 /** 1028 * Indicates if the end user has expressed an explicit opinion about the 1029 * meteredness of this network, such as through the Settings app. 1030 * This value is one of {@link #METERED_OVERRIDE_NONE}, {@link #METERED_OVERRIDE_METERED}, 1031 * or {@link #METERED_OVERRIDE_NOT_METERED}. 1032 * <p> 1033 * This should always override any values from {@link #meteredHint} or 1034 * {@link WifiInfo#getMeteredHint()}. 1035 * 1036 * By default this field is set to {@link #METERED_OVERRIDE_NONE}. 1037 * 1038 * @see #isMetered(WifiConfiguration, WifiInfo) 1039 * @hide 1040 */ 1041 @SystemApi 1042 @MeteredOverride 1043 public int meteredOverride = METERED_OVERRIDE_NONE; 1044 1045 /** 1046 * Blend together all the various opinions to decide if the given network 1047 * should be considered metered or not. 1048 * 1049 * @hide 1050 */ 1051 @SystemApi isMetered(@ullable WifiConfiguration config, @Nullable WifiInfo info)1052 public static boolean isMetered(@Nullable WifiConfiguration config, @Nullable WifiInfo info) { 1053 boolean metered = false; 1054 if (info != null && info.getMeteredHint()) { 1055 metered = true; 1056 } 1057 if (config != null && config.meteredHint) { 1058 metered = true; 1059 } 1060 if (config != null 1061 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) { 1062 metered = true; 1063 } 1064 if (config != null 1065 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) { 1066 metered = false; 1067 } 1068 return metered; 1069 } 1070 1071 /** 1072 * @hide 1073 * Returns true if this WiFi config is for an open network. 1074 */ isOpenNetwork()1075 public boolean isOpenNetwork() { 1076 final int cardinality = allowedKeyManagement.cardinality(); 1077 final boolean hasNoKeyMgmt = cardinality == 0 1078 || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE) 1079 || allowedKeyManagement.get(KeyMgmt.OWE))); 1080 1081 boolean hasNoWepKeys = true; 1082 if (wepKeys != null) { 1083 for (int i = 0; i < wepKeys.length; i++) { 1084 if (wepKeys[i] != null) { 1085 hasNoWepKeys = false; 1086 break; 1087 } 1088 } 1089 } 1090 1091 return hasNoKeyMgmt && hasNoWepKeys; 1092 } 1093 1094 /** 1095 * @hide 1096 * Setting this value will force scan results associated with this configuration to 1097 * be included in the bucket of networks that are externally scored. 1098 * If not set, associated scan results will be treated as legacy saved networks and 1099 * will take precedence over networks in the scored category. 1100 */ 1101 @SystemApi 1102 public boolean useExternalScores; 1103 1104 /** 1105 * @hide 1106 * Number of time the scorer overrode a the priority based choice, when comparing two 1107 * WifiConfigurations, note that since comparing WifiConfiguration happens very often 1108 * potentially at every scan, this number might become very large, even on an idle 1109 * system. 1110 */ 1111 @SystemApi 1112 public int numScorerOverride; 1113 1114 /** 1115 * @hide 1116 * Number of time the scorer overrode a the priority based choice, and the comparison 1117 * triggered a network switch 1118 */ 1119 @SystemApi 1120 public int numScorerOverrideAndSwitchedNetwork; 1121 1122 /** 1123 * @hide 1124 * Number of time we associated to this configuration. 1125 */ 1126 @SystemApi 1127 public int numAssociation; 1128 1129 /** @hide */ 1130 @Retention(RetentionPolicy.SOURCE) 1131 @IntDef(prefix = {"RANDOMIZATION_"}, value = { 1132 RANDOMIZATION_NONE, 1133 RANDOMIZATION_PERSISTENT}) 1134 public @interface MacRandomizationSetting {} 1135 1136 /** 1137 * Use factory MAC when connecting to this network 1138 * @hide 1139 */ 1140 @SystemApi 1141 public static final int RANDOMIZATION_NONE = 0; 1142 /** 1143 * Generate a randomized MAC once and reuse it for all connections to this network 1144 * @hide 1145 */ 1146 @SystemApi 1147 public static final int RANDOMIZATION_PERSISTENT = 1; 1148 1149 /** 1150 * Level of MAC randomization for this network. 1151 * One of {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}. 1152 * By default this field is set to {@link #RANDOMIZATION_PERSISTENT}. 1153 * @hide 1154 */ 1155 @SystemApi 1156 @MacRandomizationSetting 1157 public int macRandomizationSetting = RANDOMIZATION_PERSISTENT; 1158 1159 /** 1160 * @hide 1161 * Randomized MAC address to use with this particular network 1162 */ 1163 @NonNull 1164 private MacAddress mRandomizedMacAddress; 1165 1166 /** 1167 * @hide 1168 * The wall clock time of when |mRandomizedMacAddress| should be re-randomized in aggressive 1169 * randomization mode. 1170 */ 1171 public long randomizedMacExpirationTimeMs = 0; 1172 1173 /** 1174 * @hide 1175 * Checks if the given MAC address can be used for Connected Mac Randomization 1176 * by verifying that it is non-null, unicast, locally assigned, and not default mac. 1177 * @param mac MacAddress to check 1178 * @return true if mac is good to use 1179 */ isValidMacAddressForRandomization(MacAddress mac)1180 public static boolean isValidMacAddressForRandomization(MacAddress mac) { 1181 return mac != null && !MacAddressUtils.isMulticastAddress(mac) && mac.isLocallyAssigned() 1182 && !MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS).equals(mac); 1183 } 1184 1185 /** 1186 * Returns MAC address set to be the local randomized MAC address. 1187 * Depending on user preference, the device may or may not use the returned MAC address for 1188 * connections to this network. 1189 * <p> 1190 * Information is restricted to Device Owner, Profile Owner, and Carrier apps 1191 * (which will only obtain addresses for configurations which they create). Other callers 1192 * will receive a default "02:00:00:00:00:00" MAC address. 1193 */ getRandomizedMacAddress()1194 public @NonNull MacAddress getRandomizedMacAddress() { 1195 return mRandomizedMacAddress; 1196 } 1197 1198 /** 1199 * @hide 1200 * @param mac MacAddress to change into 1201 */ setRandomizedMacAddress(@onNull MacAddress mac)1202 public void setRandomizedMacAddress(@NonNull MacAddress mac) { 1203 if (mac == null) { 1204 Log.e(TAG, "setRandomizedMacAddress received null MacAddress."); 1205 return; 1206 } 1207 mRandomizedMacAddress = mac; 1208 } 1209 1210 /** @hide 1211 * Boost given to RSSI on a home network for the purpose of calculating the score 1212 * This adds stickiness to home networks, as defined by: 1213 * - less than 4 known BSSIDs 1214 * - PSK only 1215 * - TODO: add a test to verify that all BSSIDs are behind same gateway 1216 ***/ 1217 public static final int HOME_NETWORK_RSSI_BOOST = 5; 1218 1219 /** 1220 * This class is used to contain all the information and API used for quality network selection. 1221 * @hide 1222 */ 1223 @SystemApi 1224 public static class NetworkSelectionStatus { 1225 /** @hide */ 1226 @Retention(RetentionPolicy.SOURCE) 1227 @IntDef(prefix = "NETWORK_SELECTION_", 1228 value = { 1229 NETWORK_SELECTION_ENABLED, 1230 NETWORK_SELECTION_TEMPORARY_DISABLED, 1231 NETWORK_SELECTION_PERMANENTLY_DISABLED}) 1232 public @interface NetworkEnabledStatus {} 1233 /** 1234 * This network will be considered as a potential candidate to connect to during network 1235 * selection. 1236 */ 1237 public static final int NETWORK_SELECTION_ENABLED = 0; 1238 /** 1239 * This network was temporary disabled. May be re-enabled after a time out. 1240 */ 1241 public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; 1242 /** 1243 * This network was permanently disabled. 1244 */ 1245 public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; 1246 /** 1247 * Maximum Network selection status 1248 * @hide 1249 */ 1250 public static final int NETWORK_SELECTION_STATUS_MAX = 3; 1251 1252 /** 1253 * Quality network selection status String (for debug purpose). Use Quality network 1254 * selection status value as index to extec the corresponding debug string 1255 * @hide 1256 */ 1257 public static final String[] QUALITY_NETWORK_SELECTION_STATUS = { 1258 "NETWORK_SELECTION_ENABLED", 1259 "NETWORK_SELECTION_TEMPORARY_DISABLED", 1260 "NETWORK_SELECTION_PERMANENTLY_DISABLED"}; 1261 1262 /** @hide */ 1263 @Retention(RetentionPolicy.SOURCE) 1264 @IntDef(prefix = "DISABLED_", value = { 1265 DISABLED_NONE, 1266 DISABLED_ASSOCIATION_REJECTION, 1267 DISABLED_AUTHENTICATION_FAILURE, 1268 DISABLED_DHCP_FAILURE, 1269 DISABLED_NO_INTERNET_TEMPORARY, 1270 DISABLED_AUTHENTICATION_NO_CREDENTIALS, 1271 DISABLED_NO_INTERNET_PERMANENT, 1272 DISABLED_BY_WIFI_MANAGER, 1273 DISABLED_BY_WRONG_PASSWORD, 1274 DISABLED_AUTHENTICATION_NO_SUBSCRIPTION}) 1275 public @interface NetworkSelectionDisableReason {} 1276 1277 // Quality Network disabled reasons 1278 /** Default value. Means not disabled. */ 1279 public static final int DISABLED_NONE = 0; 1280 /** 1281 * The starting index for network selection disabled reasons. 1282 * @hide 1283 */ 1284 public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1; 1285 /** 1286 * The starting index for network selection temporarily disabled reasons. 1287 * @hide 1288 */ 1289 public static final int TEMPORARILY_DISABLED_STARTING_INDEX = 1; 1290 /** This network is disabled because of multiple association rejections. */ 1291 public static final int DISABLED_ASSOCIATION_REJECTION = 1; 1292 /** This network is disabled because of multiple authentication failure. */ 1293 public static final int DISABLED_AUTHENTICATION_FAILURE = 2; 1294 /** This network is disabled because of multiple DHCP failure. */ 1295 public static final int DISABLED_DHCP_FAILURE = 3; 1296 /** This network is temporarily disabled because it has no Internet access. */ 1297 public static final int DISABLED_NO_INTERNET_TEMPORARY = 4; 1298 /** 1299 * The starting index for network selection permanently disabled reasons. 1300 * @hide 1301 */ 1302 public static final int PERMANENTLY_DISABLED_STARTING_INDEX = 5; 1303 /** This network is disabled due to absence of user credentials */ 1304 public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5; 1305 /** 1306 * This network is permanently disabled because it has no Internet access and the user does 1307 * not want to stay connected. 1308 */ 1309 public static final int DISABLED_NO_INTERNET_PERMANENT = 6; 1310 /** This network is disabled due to WifiManager disabling it explicitly. */ 1311 public static final int DISABLED_BY_WIFI_MANAGER = 7; 1312 /** This network is disabled due to wrong password. */ 1313 public static final int DISABLED_BY_WRONG_PASSWORD = 8; 1314 /** This network is disabled because service is not subscribed. */ 1315 public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; 1316 /** 1317 * All other disable reasons should be strictly less than this value. 1318 * @hide 1319 */ 1320 public static final int NETWORK_SELECTION_DISABLED_MAX = 10; 1321 1322 /** 1323 * Get an integer that is equal to the maximum integer value of all the 1324 * DISABLED_* reasons 1325 * e.g. {@link #DISABLED_NONE}, {@link #DISABLED_ASSOCIATION_REJECTION}, etc. 1326 * 1327 * All DISABLED_* constants will be contiguous in the range 1328 * 0, 1, 2, 3, ..., getMaxNetworkSelectionDisableReasons() 1329 * 1330 * <br /> 1331 * For example, this can be used to iterate through all the network selection 1332 * disable reasons like so: 1333 * <pre>{@code 1334 * for (int reason = 0; reason <= getMaxNetworkSelectionDisableReasons(); reason++) { 1335 * ... 1336 * } 1337 * }</pre> 1338 */ getMaxNetworkSelectionDisableReason()1339 public static int getMaxNetworkSelectionDisableReason() { 1340 return NETWORK_SELECTION_DISABLED_MAX - 1; 1341 } 1342 1343 /** 1344 * Contains info about disable reasons. 1345 * @hide 1346 */ 1347 public static final class DisableReasonInfo { 1348 /** 1349 * String representation for the disable reason. 1350 * Note that these strings are persisted in 1351 * {@link 1352 * com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil#writeToXml}, 1353 * so do not change the string values to maintain backwards compatibility. 1354 */ 1355 public final String mReasonStr; 1356 /** 1357 * Network Selection disable reason threshold, used to debounce network failures before 1358 * we disable them. 1359 */ 1360 public final int mDisableThreshold; 1361 /** 1362 * Network Selection disable timeout for the error. After the timeout milliseconds, 1363 * enable the network again. 1364 */ 1365 public final int mDisableTimeoutMillis; 1366 1367 /** 1368 * Constructor 1369 * @param reasonStr string representation of the error 1370 * @param disableThreshold number of failures before we disable the network 1371 * @param disableTimeoutMillis the timeout, in milliseconds, before we re-enable the 1372 * network after disabling it 1373 */ DisableReasonInfo(String reasonStr, int disableThreshold, int disableTimeoutMillis)1374 public DisableReasonInfo(String reasonStr, int disableThreshold, 1375 int disableTimeoutMillis) { 1376 mReasonStr = reasonStr; 1377 mDisableThreshold = disableThreshold; 1378 mDisableTimeoutMillis = disableTimeoutMillis; 1379 } 1380 } 1381 1382 /** 1383 * Quality network selection disable reason infos. 1384 * @hide 1385 */ 1386 public static final SparseArray<DisableReasonInfo> DISABLE_REASON_INFOS = 1387 buildDisableReasonInfos(); 1388 buildDisableReasonInfos()1389 private static SparseArray<DisableReasonInfo> buildDisableReasonInfos() { 1390 SparseArray<DisableReasonInfo> reasons = new SparseArray<>(); 1391 1392 reasons.append(DISABLED_NONE, 1393 new DisableReasonInfo( 1394 // Note that these strings are persisted in 1395 // XmlUtil.NetworkSelectionStatusXmlUtil#writeToXml, 1396 // so do not change the string values to maintain backwards 1397 // compatibility. 1398 "NETWORK_SELECTION_ENABLE", 1399 -1, 1400 Integer.MAX_VALUE)); 1401 1402 reasons.append(DISABLED_ASSOCIATION_REJECTION, 1403 new DisableReasonInfo( 1404 // Note that there is a space at the end of this string. Cannot fix 1405 // since this string is persisted. 1406 "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ", 1407 5, 1408 5 * 60 * 1000)); 1409 1410 reasons.append(DISABLED_AUTHENTICATION_FAILURE, 1411 new DisableReasonInfo( 1412 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE", 1413 5, 1414 5 * 60 * 1000)); 1415 1416 reasons.append(DISABLED_DHCP_FAILURE, 1417 new DisableReasonInfo( 1418 "NETWORK_SELECTION_DISABLED_DHCP_FAILURE", 1419 5, 1420 5 * 60 * 1000)); 1421 1422 reasons.append(DISABLED_NO_INTERNET_TEMPORARY, 1423 new DisableReasonInfo( 1424 "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY", 1425 1, 1426 10 * 60 * 1000)); 1427 1428 reasons.append(DISABLED_AUTHENTICATION_NO_CREDENTIALS, 1429 new DisableReasonInfo( 1430 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS", 1431 1, 1432 Integer.MAX_VALUE)); 1433 1434 reasons.append(DISABLED_NO_INTERNET_PERMANENT, 1435 new DisableReasonInfo( 1436 "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT", 1437 1, 1438 Integer.MAX_VALUE)); 1439 1440 reasons.append(DISABLED_BY_WIFI_MANAGER, 1441 new DisableReasonInfo( 1442 "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER", 1443 1, 1444 Integer.MAX_VALUE)); 1445 1446 reasons.append(DISABLED_BY_WRONG_PASSWORD, 1447 new DisableReasonInfo( 1448 "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD", 1449 1, 1450 Integer.MAX_VALUE)); 1451 1452 reasons.append(DISABLED_AUTHENTICATION_NO_SUBSCRIPTION, 1453 new DisableReasonInfo( 1454 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION", 1455 1, 1456 Integer.MAX_VALUE)); 1457 1458 return reasons; 1459 } 1460 1461 /** 1462 * Get the {@link NetworkSelectionDisableReason} int code by its string value. 1463 * @return the NetworkSelectionDisableReason int code corresponding to the reason string, 1464 * or -1 if the reason string is unrecognized. 1465 * @hide 1466 */ 1467 @NetworkSelectionDisableReason getDisableReasonByString(@onNull String reasonString)1468 public static int getDisableReasonByString(@NonNull String reasonString) { 1469 for (int i = 0; i < DISABLE_REASON_INFOS.size(); i++) { 1470 int key = DISABLE_REASON_INFOS.keyAt(i); 1471 DisableReasonInfo value = DISABLE_REASON_INFOS.valueAt(i); 1472 if (value != null && TextUtils.equals(reasonString, value.mReasonStr)) { 1473 return key; 1474 } 1475 } 1476 Log.e(TAG, "Unrecognized network disable reason: " + reasonString); 1477 return -1; 1478 } 1479 1480 /** 1481 * Invalid time stamp for network selection disable 1482 * @hide 1483 */ 1484 public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L; 1485 1486 /** 1487 * This constant indicates the current configuration has connect choice set 1488 */ 1489 private static final int CONNECT_CHOICE_EXISTS = 1; 1490 1491 /** 1492 * This constant indicates the current configuration does not have connect choice set 1493 */ 1494 private static final int CONNECT_CHOICE_NOT_EXISTS = -1; 1495 1496 // fields for QualityNetwork Selection 1497 /** 1498 * Network selection status, should be in one of three status: enable, temporaily disabled 1499 * or permanently disabled 1500 */ 1501 @NetworkEnabledStatus 1502 private int mStatus; 1503 1504 /** 1505 * Reason for disable this network 1506 */ 1507 @NetworkSelectionDisableReason 1508 private int mNetworkSelectionDisableReason; 1509 1510 /** 1511 * Last time we temporarily disabled the configuration 1512 */ 1513 private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 1514 1515 /** 1516 * counter for each Network selection disable reason 1517 */ 1518 private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX]; 1519 1520 /** 1521 * Connect Choice over this configuration 1522 * 1523 * When current wifi configuration is visible to the user but user explicitly choose to 1524 * connect to another network X, the another networks X's configure key will be stored here. 1525 * We will consider user has a preference of X over this network. And in the future, 1526 * network selection will always give X a higher preference over this configuration. 1527 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 1528 */ 1529 private String mConnectChoice; 1530 1531 /** 1532 * Used to cache the temporary candidate during the network selection procedure. It will be 1533 * kept updating once a new scan result has a higher score than current one 1534 */ 1535 private ScanResult mCandidate; 1536 1537 /** 1538 * Used to cache the score of the current temporary candidate during the network 1539 * selection procedure. 1540 */ 1541 private int mCandidateScore; 1542 1543 /** 1544 * Indicate whether this network is visible in latest Qualified Network Selection. This 1545 * means there is scan result found related to this Configuration and meet the minimum 1546 * requirement. The saved network need not join latest Qualified Network Selection. For 1547 * example, it is disabled. True means network is visible in latest Qualified Network 1548 * Selection and false means network is invisible 1549 */ 1550 private boolean mSeenInLastQualifiedNetworkSelection; 1551 1552 /** 1553 * Boolean indicating if we have ever successfully connected to this network. 1554 * 1555 * This value will be set to true upon a successful connection. 1556 * This value will be set to false if a previous value was not stored in the config or if 1557 * the credentials are updated (ex. a password change). 1558 */ 1559 private boolean mHasEverConnected; 1560 1561 /** 1562 * set whether this network is visible in latest Qualified Network Selection 1563 * @param seen value set to candidate 1564 * @hide 1565 */ setSeenInLastQualifiedNetworkSelection(boolean seen)1566 public void setSeenInLastQualifiedNetworkSelection(boolean seen) { 1567 mSeenInLastQualifiedNetworkSelection = seen; 1568 } 1569 1570 /** 1571 * get whether this network is visible in latest Qualified Network Selection 1572 * @return returns true -- network is visible in latest Qualified Network Selection 1573 * false -- network is invisible in latest Qualified Network Selection 1574 * @hide 1575 */ getSeenInLastQualifiedNetworkSelection()1576 public boolean getSeenInLastQualifiedNetworkSelection() { 1577 return mSeenInLastQualifiedNetworkSelection; 1578 } 1579 /** 1580 * set the temporary candidate of current network selection procedure 1581 * @param scanCandidate {@link ScanResult} the candidate set to mCandidate 1582 * @hide 1583 */ setCandidate(ScanResult scanCandidate)1584 public void setCandidate(ScanResult scanCandidate) { 1585 mCandidate = scanCandidate; 1586 } 1587 1588 /** 1589 * get the temporary candidate of current network selection procedure 1590 * @return returns {@link ScanResult} temporary candidate of current network selection 1591 * procedure 1592 * @hide 1593 */ getCandidate()1594 public ScanResult getCandidate() { 1595 return mCandidate; 1596 } 1597 1598 /** 1599 * set the score of the temporary candidate of current network selection procedure 1600 * @param score value set to mCandidateScore 1601 * @hide 1602 */ setCandidateScore(int score)1603 public void setCandidateScore(int score) { 1604 mCandidateScore = score; 1605 } 1606 1607 /** 1608 * get the score of the temporary candidate of current network selection procedure 1609 * @return returns score of the temporary candidate of current network selection procedure 1610 * @hide 1611 */ getCandidateScore()1612 public int getCandidateScore() { 1613 return mCandidateScore; 1614 } 1615 1616 /** 1617 * get user preferred choice over this configuration 1618 * @return returns configKey of user preferred choice over this configuration 1619 * @hide 1620 */ getConnectChoice()1621 public String getConnectChoice() { 1622 return mConnectChoice; 1623 } 1624 1625 /** 1626 * set user preferred choice over this configuration 1627 * @param newConnectChoice, the configKey of user preferred choice over this configuration 1628 * @hide 1629 */ setConnectChoice(String newConnectChoice)1630 public void setConnectChoice(String newConnectChoice) { 1631 mConnectChoice = newConnectChoice; 1632 } 1633 1634 /** Get the current Quality network selection status as a String (for debugging). */ 1635 @NonNull getNetworkStatusString()1636 public String getNetworkStatusString() { 1637 return QUALITY_NETWORK_SELECTION_STATUS[mStatus]; 1638 } 1639 1640 /** @hide */ setHasEverConnected(boolean value)1641 public void setHasEverConnected(boolean value) { 1642 mHasEverConnected = value; 1643 } 1644 1645 /** True if the device has ever connected to this network, false otherwise. */ hasEverConnected()1646 public boolean hasEverConnected() { 1647 return mHasEverConnected; 1648 } 1649 1650 /** @hide */ NetworkSelectionStatus()1651 public NetworkSelectionStatus() { 1652 // previously stored configs will not have this parameter, so we default to false. 1653 mHasEverConnected = false; 1654 } 1655 1656 /** 1657 * NetworkSelectionStatus exports an immutable public API. 1658 * However, test code has a need to construct a NetworkSelectionStatus in a specific state. 1659 * (Note that mocking using Mockito does not work if the object needs to be parceled and 1660 * unparceled.) 1661 * Export a @SystemApi Builder to allow tests to construct a NetworkSelectionStatus object 1662 * in the desired state, without sacrificing NetworkSelectionStatus's immutability. 1663 */ 1664 @VisibleForTesting 1665 public static final class Builder { 1666 private final NetworkSelectionStatus mNetworkSelectionStatus = 1667 new NetworkSelectionStatus(); 1668 1669 /** 1670 * Set the current network selection status. 1671 * One of: 1672 * {@link #NETWORK_SELECTION_ENABLED}, 1673 * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED}, 1674 * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED} 1675 * @see NetworkSelectionStatus#getNetworkSelectionStatus() 1676 */ 1677 @NonNull setNetworkSelectionStatus(@etworkEnabledStatus int status)1678 public Builder setNetworkSelectionStatus(@NetworkEnabledStatus int status) { 1679 mNetworkSelectionStatus.setNetworkSelectionStatus(status); 1680 return this; 1681 } 1682 1683 /** 1684 * 1685 * Set the current network's disable reason. 1686 * One of the {@link #DISABLED_NONE} or DISABLED_* constants. 1687 * e.g. {@link #DISABLED_ASSOCIATION_REJECTION}. 1688 * @see NetworkSelectionStatus#getNetworkSelectionDisableReason() 1689 */ 1690 @NonNull setNetworkSelectionDisableReason( @etworkSelectionDisableReason int reason)1691 public Builder setNetworkSelectionDisableReason( 1692 @NetworkSelectionDisableReason int reason) { 1693 mNetworkSelectionStatus.setNetworkSelectionDisableReason(reason); 1694 return this; 1695 } 1696 1697 /** 1698 * Build a NetworkSelectionStatus object. 1699 */ 1700 @NonNull build()1701 public NetworkSelectionStatus build() { 1702 NetworkSelectionStatus status = new NetworkSelectionStatus(); 1703 status.copy(mNetworkSelectionStatus); 1704 return status; 1705 } 1706 } 1707 1708 /** 1709 * Get the network disable reason string for a reason code (for debugging). 1710 * @param reason specific error reason. One of the {@link #DISABLED_NONE} or 1711 * DISABLED_* constants e.g. {@link #DISABLED_ASSOCIATION_REJECTION}. 1712 * @return network disable reason string, or null if the reason is invalid. 1713 */ 1714 @Nullable getNetworkSelectionDisableReasonString( @etworkSelectionDisableReason int reason)1715 public static String getNetworkSelectionDisableReasonString( 1716 @NetworkSelectionDisableReason int reason) { 1717 DisableReasonInfo info = DISABLE_REASON_INFOS.get(reason); 1718 if (info == null) { 1719 return null; 1720 } else { 1721 return info.mReasonStr; 1722 } 1723 } 1724 /** 1725 * get current network disable reason 1726 * @return current network disable reason in String (for debug purpose) 1727 * @hide 1728 */ getNetworkSelectionDisableReasonString()1729 public String getNetworkSelectionDisableReasonString() { 1730 return getNetworkSelectionDisableReasonString(mNetworkSelectionDisableReason); 1731 } 1732 1733 /** 1734 * Get the current network network selection status. 1735 * One of: 1736 * {@link #NETWORK_SELECTION_ENABLED}, 1737 * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED}, 1738 * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED} 1739 */ 1740 @NetworkEnabledStatus getNetworkSelectionStatus()1741 public int getNetworkSelectionStatus() { 1742 return mStatus; 1743 } 1744 1745 /** 1746 * True if the current network is enabled to join network selection, false otherwise. 1747 * @hide 1748 */ isNetworkEnabled()1749 public boolean isNetworkEnabled() { 1750 return mStatus == NETWORK_SELECTION_ENABLED; 1751 } 1752 1753 /** 1754 * @return whether current network is temporary disabled 1755 * @hide 1756 */ isNetworkTemporaryDisabled()1757 public boolean isNetworkTemporaryDisabled() { 1758 return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED; 1759 } 1760 1761 /** 1762 * True if the current network is permanently disabled, false otherwise. 1763 * @hide 1764 */ isNetworkPermanentlyDisabled()1765 public boolean isNetworkPermanentlyDisabled() { 1766 return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED; 1767 } 1768 1769 /** 1770 * set current network selection status 1771 * @param status network selection status to set 1772 * @hide 1773 */ setNetworkSelectionStatus(int status)1774 public void setNetworkSelectionStatus(int status) { 1775 if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) { 1776 mStatus = status; 1777 } 1778 } 1779 1780 /** 1781 * Returns the current network's disable reason. 1782 * One of the {@link #DISABLED_NONE} or DISABLED_* constants 1783 * e.g. {@link #DISABLED_ASSOCIATION_REJECTION}. 1784 */ 1785 @NetworkSelectionDisableReason getNetworkSelectionDisableReason()1786 public int getNetworkSelectionDisableReason() { 1787 return mNetworkSelectionDisableReason; 1788 } 1789 1790 /** 1791 * set Network disable reason 1792 * @param reason Network disable reason 1793 * @hide 1794 */ setNetworkSelectionDisableReason(@etworkSelectionDisableReason int reason)1795 public void setNetworkSelectionDisableReason(@NetworkSelectionDisableReason int reason) { 1796 if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) { 1797 mNetworkSelectionDisableReason = reason; 1798 } else { 1799 throw new IllegalArgumentException("Illegal reason value: " + reason); 1800 } 1801 } 1802 1803 /** 1804 * @param timeStamp Set when current network is disabled in millisecond since January 1, 1805 * 1970 00:00:00.0 UTC 1806 * @hide 1807 */ setDisableTime(long timeStamp)1808 public void setDisableTime(long timeStamp) { 1809 mTemporarilyDisabledTimestamp = timeStamp; 1810 } 1811 1812 /** 1813 * Returns when the current network was disabled, in milliseconds since January 1, 1814 * 1970 00:00:00.0 UTC. 1815 */ getDisableTime()1816 public long getDisableTime() { 1817 return mTemporarilyDisabledTimestamp; 1818 } 1819 1820 /** 1821 * Get the disable counter of a specific reason. 1822 * @param reason specific failure reason. One of the {@link #DISABLED_NONE} or 1823 * DISABLED_* constants e.g. {@link #DISABLED_ASSOCIATION_REJECTION}. 1824 * @exception IllegalArgumentException for invalid reason 1825 * @return counter number for specific error reason. 1826 */ getDisableReasonCounter(@etworkSelectionDisableReason int reason)1827 public int getDisableReasonCounter(@NetworkSelectionDisableReason int reason) { 1828 if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1829 return mNetworkSeclectionDisableCounter[reason]; 1830 } else { 1831 throw new IllegalArgumentException("Illegal reason value: " + reason); 1832 } 1833 } 1834 1835 /** 1836 * set the counter of a specific failure reason 1837 * @param reason reason for disable error 1838 * @param value the counter value for this specific reason 1839 * @exception throw IllegalArgumentException for illegal input 1840 * @hide 1841 */ setDisableReasonCounter(int reason, int value)1842 public void setDisableReasonCounter(int reason, int value) { 1843 if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1844 mNetworkSeclectionDisableCounter[reason] = value; 1845 } else { 1846 throw new IllegalArgumentException("Illegal reason value: " + reason); 1847 } 1848 } 1849 1850 /** 1851 * increment the counter of a specific failure reason 1852 * @param reason a specific failure reason 1853 * @exception throw IllegalArgumentException for illegal input 1854 * @hide 1855 */ incrementDisableReasonCounter(int reason)1856 public void incrementDisableReasonCounter(int reason) { 1857 if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1858 mNetworkSeclectionDisableCounter[reason]++; 1859 } else { 1860 throw new IllegalArgumentException("Illegal reason value: " + reason); 1861 } 1862 } 1863 1864 /** 1865 * clear the counter of a specific failure reason 1866 * @param reason a specific failure reason 1867 * @exception throw IllegalArgumentException for illegal input 1868 * @hide 1869 */ clearDisableReasonCounter(int reason)1870 public void clearDisableReasonCounter(int reason) { 1871 if (reason >= DISABLED_NONE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1872 mNetworkSeclectionDisableCounter[reason] = DISABLED_NONE; 1873 } else { 1874 throw new IllegalArgumentException("Illegal reason value: " + reason); 1875 } 1876 } 1877 1878 /** 1879 * clear all the failure reason counters 1880 * @hide 1881 */ clearDisableReasonCounter()1882 public void clearDisableReasonCounter() { 1883 Arrays.fill(mNetworkSeclectionDisableCounter, DISABLED_NONE); 1884 } 1885 1886 /** 1887 * BSSID for connection to this network (through network selection procedure) 1888 */ 1889 private String mNetworkSelectionBSSID; 1890 1891 /** 1892 * get current network Selection BSSID 1893 * @return current network Selection BSSID 1894 * @hide 1895 */ getNetworkSelectionBSSID()1896 public String getNetworkSelectionBSSID() { 1897 return mNetworkSelectionBSSID; 1898 } 1899 1900 /** 1901 * set network Selection BSSID 1902 * @param bssid The target BSSID for assocaition 1903 * @hide 1904 */ setNetworkSelectionBSSID(String bssid)1905 public void setNetworkSelectionBSSID(String bssid) { 1906 mNetworkSelectionBSSID = bssid; 1907 } 1908 1909 /** @hide */ copy(NetworkSelectionStatus source)1910 public void copy(NetworkSelectionStatus source) { 1911 mStatus = source.mStatus; 1912 mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason; 1913 for (int index = DISABLED_NONE; index < NETWORK_SELECTION_DISABLED_MAX; 1914 index++) { 1915 mNetworkSeclectionDisableCounter[index] = 1916 source.mNetworkSeclectionDisableCounter[index]; 1917 } 1918 mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp; 1919 mNetworkSelectionBSSID = source.mNetworkSelectionBSSID; 1920 setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection()); 1921 setCandidate(source.getCandidate()); 1922 setCandidateScore(source.getCandidateScore()); 1923 setConnectChoice(source.getConnectChoice()); 1924 setHasEverConnected(source.hasEverConnected()); 1925 } 1926 1927 /** @hide */ writeToParcel(Parcel dest)1928 public void writeToParcel(Parcel dest) { 1929 dest.writeInt(getNetworkSelectionStatus()); 1930 dest.writeInt(getNetworkSelectionDisableReason()); 1931 for (int index = DISABLED_NONE; index < NETWORK_SELECTION_DISABLED_MAX; 1932 index++) { 1933 dest.writeInt(getDisableReasonCounter(index)); 1934 } 1935 dest.writeLong(getDisableTime()); 1936 dest.writeString(getNetworkSelectionBSSID()); 1937 if (getConnectChoice() != null) { 1938 dest.writeInt(CONNECT_CHOICE_EXISTS); 1939 dest.writeString(getConnectChoice()); 1940 } else { 1941 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); 1942 } 1943 dest.writeInt(hasEverConnected() ? 1 : 0); 1944 } 1945 1946 /** @hide */ readFromParcel(Parcel in)1947 public void readFromParcel(Parcel in) { 1948 setNetworkSelectionStatus(in.readInt()); 1949 setNetworkSelectionDisableReason(in.readInt()); 1950 for (int index = DISABLED_NONE; index < NETWORK_SELECTION_DISABLED_MAX; 1951 index++) { 1952 setDisableReasonCounter(index, in.readInt()); 1953 } 1954 setDisableTime(in.readLong()); 1955 setNetworkSelectionBSSID(in.readString()); 1956 if (in.readInt() == CONNECT_CHOICE_EXISTS) { 1957 setConnectChoice(in.readString()); 1958 } else { 1959 setConnectChoice(null); 1960 } 1961 setHasEverConnected(in.readInt() != 0); 1962 } 1963 } 1964 1965 /** 1966 * @hide 1967 * network selection related member 1968 */ 1969 private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus(); 1970 1971 /** 1972 * This class is intended to store extra failure reason information for the most recent 1973 * connection attempt, so that it may be surfaced to the settings UI 1974 * @hide 1975 */ 1976 // TODO(b/148626966): called by SUW via reflection, remove once SUW is updated 1977 public static class RecentFailure { 1978 RecentFailure()1979 private RecentFailure() {} 1980 1981 /** 1982 * Association Rejection Status code (NONE for success/non-association-rejection-fail) 1983 */ 1984 @RecentFailureReason 1985 private int mAssociationStatus = RECENT_FAILURE_NONE; 1986 1987 /** 1988 * @param status the association status code for the recent failure 1989 */ setAssociationStatus(@ecentFailureReason int status)1990 public void setAssociationStatus(@RecentFailureReason int status) { 1991 mAssociationStatus = status; 1992 } 1993 /** 1994 * Sets the RecentFailure to NONE 1995 */ clear()1996 public void clear() { 1997 mAssociationStatus = RECENT_FAILURE_NONE; 1998 } 1999 /** 2000 * Get the recent failure code. One of {@link #RECENT_FAILURE_NONE} or 2001 * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}. 2002 */ 2003 @RecentFailureReason getAssociationStatus()2004 public int getAssociationStatus() { 2005 return mAssociationStatus; 2006 } 2007 } 2008 2009 /** 2010 * RecentFailure member 2011 * @hide 2012 */ 2013 // TODO(b/148626966): called by SUW via reflection, once SUW is updated, make private and 2014 // rename to mRecentFailure 2015 @NonNull 2016 public final RecentFailure recentFailure = new RecentFailure(); 2017 2018 /** @hide */ 2019 @Retention(RetentionPolicy.SOURCE) 2020 @IntDef(prefix = "RECENT_FAILURE_", value = { 2021 RECENT_FAILURE_NONE, 2022 RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}) 2023 public @interface RecentFailureReason {} 2024 2025 /** 2026 * No recent failure, or no specific reason given for the recent connection failure 2027 * @hide 2028 */ 2029 @SystemApi 2030 public static final int RECENT_FAILURE_NONE = 0; 2031 /** 2032 * Connection to this network recently failed due to Association Rejection Status 17 2033 * (AP is full) 2034 * @hide 2035 */ 2036 @SystemApi 2037 public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; 2038 2039 /** 2040 * Get the failure reason for the most recent connection attempt, or 2041 * {@link #RECENT_FAILURE_NONE} if there was no failure. 2042 * 2043 * Failure reasons include: 2044 * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA} 2045 * 2046 * @hide 2047 */ 2048 @RecentFailureReason 2049 @SystemApi getRecentFailureReason()2050 public int getRecentFailureReason() { 2051 return recentFailure.getAssociationStatus(); 2052 } 2053 2054 /** 2055 * Get the network selection status. 2056 * @hide 2057 */ 2058 @NonNull 2059 @SystemApi getNetworkSelectionStatus()2060 public NetworkSelectionStatus getNetworkSelectionStatus() { 2061 return mNetworkSelectionStatus; 2062 } 2063 2064 /** 2065 * Set the network selection status. 2066 * @hide 2067 */ 2068 @SystemApi setNetworkSelectionStatus(@onNull NetworkSelectionStatus status)2069 public void setNetworkSelectionStatus(@NonNull NetworkSelectionStatus status) { 2070 mNetworkSelectionStatus = status; 2071 } 2072 2073 /** 2074 * @hide 2075 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 2076 * regarding roaming and auto-joining. 2077 * The linked configuration may or may not have same SSID, and may or may not have same 2078 * credentials. 2079 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 2080 */ 2081 public HashMap<String, Integer> linkedConfigurations; 2082 WifiConfiguration()2083 public WifiConfiguration() { 2084 networkId = INVALID_NETWORK_ID; 2085 SSID = null; 2086 BSSID = null; 2087 FQDN = null; 2088 roamingConsortiumIds = new long[0]; 2089 priority = 0; 2090 hiddenSSID = false; 2091 allowedKeyManagement = new BitSet(); 2092 allowedProtocols = new BitSet(); 2093 allowedAuthAlgorithms = new BitSet(); 2094 allowedPairwiseCiphers = new BitSet(); 2095 allowedGroupCiphers = new BitSet(); 2096 allowedGroupManagementCiphers = new BitSet(); 2097 allowedSuiteBCiphers = new BitSet(); 2098 wepKeys = new String[4]; 2099 for (int i = 0; i < wepKeys.length; i++) { 2100 wepKeys[i] = null; 2101 } 2102 enterpriseConfig = new WifiEnterpriseConfig(); 2103 ephemeral = false; 2104 osu = false; 2105 trusted = true; // Networks are considered trusted by default. 2106 fromWifiNetworkSuggestion = false; 2107 fromWifiNetworkSpecifier = false; 2108 meteredHint = false; 2109 meteredOverride = METERED_OVERRIDE_NONE; 2110 useExternalScores = false; 2111 validatedInternetAccess = false; 2112 mIpConfiguration = new IpConfiguration(); 2113 lastUpdateUid = -1; 2114 creatorUid = -1; 2115 shared = true; 2116 dtimInterval = 0; 2117 mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); 2118 } 2119 2120 /** 2121 * Identify if this configuration represents a Passpoint network 2122 */ isPasspoint()2123 public boolean isPasspoint() { 2124 return !TextUtils.isEmpty(FQDN) 2125 && !TextUtils.isEmpty(providerFriendlyName) 2126 && enterpriseConfig != null 2127 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE 2128 && !TextUtils.isEmpty(mPasspointUniqueId); 2129 } 2130 2131 /** 2132 * Helper function, identify if a configuration is linked 2133 * @hide 2134 */ isLinked(WifiConfiguration config)2135 public boolean isLinked(WifiConfiguration config) { 2136 if (config != null) { 2137 if (config.linkedConfigurations != null && linkedConfigurations != null) { 2138 if (config.linkedConfigurations.get(getKey()) != null 2139 && linkedConfigurations.get(config.getKey()) != null) { 2140 return true; 2141 } 2142 } 2143 } 2144 return false; 2145 } 2146 2147 /** 2148 * Helper function, idenfity if a configuration should be treated as an enterprise network 2149 * @hide 2150 */ 2151 @UnsupportedAppUsage isEnterprise()2152 public boolean isEnterprise() { 2153 return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) 2154 || allowedKeyManagement.get(KeyMgmt.IEEE8021X) 2155 || allowedKeyManagement.get(KeyMgmt.SUITE_B_192) 2156 || allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) 2157 && enterpriseConfig != null 2158 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 2159 } 2160 logTimeOfDay(long millis)2161 private static String logTimeOfDay(long millis) { 2162 Calendar c = Calendar.getInstance(); 2163 if (millis >= 0) { 2164 c.setTimeInMillis(millis); 2165 return String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c); 2166 } else { 2167 return Long.toString(millis); 2168 } 2169 } 2170 2171 @Override toString()2172 public String toString() { 2173 StringBuilder sbuf = new StringBuilder(); 2174 if (this.status == WifiConfiguration.Status.CURRENT) { 2175 sbuf.append("* "); 2176 } else if (this.status == WifiConfiguration.Status.DISABLED) { 2177 sbuf.append("- DSBLE "); 2178 } 2179 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 2180 append(" PROVIDER-NAME: ").append(this.providerFriendlyName). 2181 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN) 2182 .append(" HOME-PROVIDER-NETWORK: ").append(this.isHomeProviderNetwork) 2183 .append(" PRIO: ").append(this.priority) 2184 .append(" HIDDEN: ").append(this.hiddenSSID) 2185 .append(" PMF: ").append(this.requirePmf) 2186 .append("CarrierId: ").append(this.carrierId) 2187 .append('\n'); 2188 2189 2190 sbuf.append(" NetworkSelectionStatus ") 2191 .append(mNetworkSelectionStatus.getNetworkStatusString()) 2192 .append("\n"); 2193 if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) { 2194 sbuf.append(" mNetworkSelectionDisableReason ") 2195 .append(mNetworkSelectionStatus.getNetworkSelectionDisableReasonString()) 2196 .append("\n"); 2197 2198 for (int index = NetworkSelectionStatus.DISABLED_NONE; 2199 index < NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) { 2200 if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) { 2201 sbuf.append( 2202 NetworkSelectionStatus.getNetworkSelectionDisableReasonString(index)) 2203 .append(" counter:") 2204 .append(mNetworkSelectionStatus.getDisableReasonCounter(index)) 2205 .append("\n"); 2206 } 2207 } 2208 } 2209 if (mNetworkSelectionStatus.getConnectChoice() != null) { 2210 sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); 2211 } 2212 sbuf.append(" hasEverConnected: ") 2213 .append(mNetworkSelectionStatus.hasEverConnected()).append("\n"); 2214 2215 if (this.numAssociation > 0) { 2216 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 2217 } 2218 if (this.numNoInternetAccessReports > 0) { 2219 sbuf.append(" numNoInternetAccessReports "); 2220 sbuf.append(this.numNoInternetAccessReports).append("\n"); 2221 } 2222 if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); 2223 if (this.ephemeral) sbuf.append(" ephemeral"); 2224 if (this.osu) sbuf.append(" osu"); 2225 if (this.trusted) sbuf.append(" trusted"); 2226 if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion"); 2227 if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier"); 2228 if (this.meteredHint) sbuf.append(" meteredHint"); 2229 if (this.useExternalScores) sbuf.append(" useExternalScores"); 2230 if (this.validatedInternetAccess || this.ephemeral || this.trusted 2231 || this.fromWifiNetworkSuggestion || this.fromWifiNetworkSpecifier 2232 || this.meteredHint || this.useExternalScores) { 2233 sbuf.append("\n"); 2234 } 2235 if (this.meteredOverride != METERED_OVERRIDE_NONE) { 2236 sbuf.append(" meteredOverride ").append(meteredOverride).append("\n"); 2237 } 2238 sbuf.append(" macRandomizationSetting: ").append(macRandomizationSetting).append("\n"); 2239 sbuf.append(" mRandomizedMacAddress: ").append(mRandomizedMacAddress).append("\n"); 2240 sbuf.append(" randomizedMacExpirationTimeMs: ") 2241 .append(randomizedMacExpirationTimeMs == 0 ? "<none>" 2242 : logTimeOfDay(randomizedMacExpirationTimeMs)).append("\n"); 2243 sbuf.append(" KeyMgmt:"); 2244 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 2245 if (this.allowedKeyManagement.get(k)) { 2246 sbuf.append(" "); 2247 if (k < KeyMgmt.strings.length) { 2248 sbuf.append(KeyMgmt.strings[k]); 2249 } else { 2250 sbuf.append("??"); 2251 } 2252 } 2253 } 2254 sbuf.append(" Protocols:"); 2255 for (int p = 0; p < this.allowedProtocols.size(); p++) { 2256 if (this.allowedProtocols.get(p)) { 2257 sbuf.append(" "); 2258 if (p < Protocol.strings.length) { 2259 sbuf.append(Protocol.strings[p]); 2260 } else { 2261 sbuf.append("??"); 2262 } 2263 } 2264 } 2265 sbuf.append('\n'); 2266 sbuf.append(" AuthAlgorithms:"); 2267 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 2268 if (this.allowedAuthAlgorithms.get(a)) { 2269 sbuf.append(" "); 2270 if (a < AuthAlgorithm.strings.length) { 2271 sbuf.append(AuthAlgorithm.strings[a]); 2272 } else { 2273 sbuf.append("??"); 2274 } 2275 } 2276 } 2277 sbuf.append('\n'); 2278 sbuf.append(" PairwiseCiphers:"); 2279 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 2280 if (this.allowedPairwiseCiphers.get(pc)) { 2281 sbuf.append(" "); 2282 if (pc < PairwiseCipher.strings.length) { 2283 sbuf.append(PairwiseCipher.strings[pc]); 2284 } else { 2285 sbuf.append("??"); 2286 } 2287 } 2288 } 2289 sbuf.append('\n'); 2290 sbuf.append(" GroupCiphers:"); 2291 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 2292 if (this.allowedGroupCiphers.get(gc)) { 2293 sbuf.append(" "); 2294 if (gc < GroupCipher.strings.length) { 2295 sbuf.append(GroupCipher.strings[gc]); 2296 } else { 2297 sbuf.append("??"); 2298 } 2299 } 2300 } 2301 sbuf.append('\n'); 2302 sbuf.append(" GroupMgmtCiphers:"); 2303 for (int gmc = 0; gmc < this.allowedGroupManagementCiphers.size(); gmc++) { 2304 if (this.allowedGroupManagementCiphers.get(gmc)) { 2305 sbuf.append(" "); 2306 if (gmc < GroupMgmtCipher.strings.length) { 2307 sbuf.append(GroupMgmtCipher.strings[gmc]); 2308 } else { 2309 sbuf.append("??"); 2310 } 2311 } 2312 } 2313 sbuf.append('\n'); 2314 sbuf.append(" SuiteBCiphers:"); 2315 for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) { 2316 if (this.allowedSuiteBCiphers.get(sbc)) { 2317 sbuf.append(" "); 2318 if (sbc < SuiteBCipher.strings.length) { 2319 sbuf.append(SuiteBCipher.strings[sbc]); 2320 } else { 2321 sbuf.append("??"); 2322 } 2323 } 2324 } 2325 sbuf.append('\n').append(" PSK/SAE: "); 2326 if (this.preSharedKey != null) { 2327 sbuf.append('*'); 2328 } 2329 2330 sbuf.append("\nEnterprise config:\n"); 2331 sbuf.append(enterpriseConfig); 2332 2333 sbuf.append("IP config:\n"); 2334 sbuf.append(mIpConfiguration.toString()); 2335 2336 if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) { 2337 sbuf.append(" networkSelectionBSSID=" 2338 + mNetworkSelectionStatus.getNetworkSelectionBSSID()); 2339 } 2340 long now_ms = SystemClock.elapsedRealtime(); 2341 if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus 2342 .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) { 2343 sbuf.append('\n'); 2344 long diff = now_ms - mNetworkSelectionStatus.getDisableTime(); 2345 if (diff <= 0) { 2346 sbuf.append(" blackListed since <incorrect>"); 2347 } else { 2348 sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec "); 2349 } 2350 } 2351 if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid); 2352 if (creatorName != null) sbuf.append(" cname=" + creatorName); 2353 if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid); 2354 if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName); 2355 if (updateIdentifier != null) sbuf.append(" updateIdentifier=" + updateIdentifier); 2356 sbuf.append(" lcuid=" + lastConnectUid); 2357 sbuf.append(" allowAutojoin=" + allowAutojoin); 2358 sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected); 2359 sbuf.append(" mostRecentlyConnected=" + isMostRecentlyConnected); 2360 2361 sbuf.append(" "); 2362 2363 if (this.lastConnected != 0) { 2364 sbuf.append('\n'); 2365 sbuf.append("lastConnected: ").append(logTimeOfDay(this.lastConnected)); 2366 sbuf.append(" "); 2367 } 2368 sbuf.append('\n'); 2369 if (this.linkedConfigurations != null) { 2370 for (String key : this.linkedConfigurations.keySet()) { 2371 sbuf.append(" linked: ").append(key); 2372 sbuf.append('\n'); 2373 } 2374 } 2375 sbuf.append("recentFailure: ").append("Association Rejection code: ") 2376 .append(recentFailure.getAssociationStatus()).append("\n"); 2377 return sbuf.toString(); 2378 } 2379 2380 /** 2381 * Get the SSID in a human-readable format, with all additional formatting removed 2382 * e.g. quotation marks around the SSID, "P" prefix 2383 * @hide 2384 */ 2385 @NonNull 2386 @SystemApi getPrintableSsid()2387 public String getPrintableSsid() { 2388 if (SSID == null) return ""; 2389 final int length = SSID.length(); 2390 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 2391 return SSID.substring(1, length - 1); 2392 } 2393 2394 /* The ascii-encoded string format is P"<ascii-encoded-string>" 2395 * The decoding is implemented in the supplicant for a newly configured 2396 * network. 2397 */ 2398 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 2399 (SSID.charAt(length-1) == '"')) { 2400 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 2401 SSID.substring(2, length - 1)); 2402 return wifiSsid.toString(); 2403 } 2404 return SSID; 2405 } 2406 2407 /** 2408 * Get an identifier for associating credentials with this config 2409 * @param current configuration contains values for additional fields 2410 * that are not part of this configuration. Used 2411 * when a config with some fields is passed by an application. 2412 * @throws IllegalStateException if config is invalid for key id generation 2413 * @hide 2414 */ getKeyIdForCredentials(WifiConfiguration current)2415 public String getKeyIdForCredentials(WifiConfiguration current) { 2416 String keyMgmt = ""; 2417 2418 try { 2419 // Get current config details for fields that are not initialized 2420 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 2421 if (allowedKeyManagement.cardinality() == 0) { 2422 allowedKeyManagement = current.allowedKeyManagement; 2423 } 2424 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 2425 keyMgmt += KeyMgmt.strings[KeyMgmt.WPA_EAP]; 2426 } 2427 if (allowedKeyManagement.get(KeyMgmt.OSEN)) { 2428 keyMgmt += KeyMgmt.strings[KeyMgmt.OSEN]; 2429 } 2430 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 2431 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 2432 } 2433 if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { 2434 keyMgmt += KeyMgmt.strings[KeyMgmt.SUITE_B_192]; 2435 } 2436 if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { 2437 keyMgmt += KeyMgmt.strings[KeyMgmt.WAPI_CERT]; 2438 } 2439 2440 if (TextUtils.isEmpty(keyMgmt)) { 2441 throw new IllegalStateException("Not an EAP network"); 2442 } 2443 String keyId = trimStringForKeyId(SSID) + "_" + keyMgmt + "_" 2444 + trimStringForKeyId(enterpriseConfig.getKeyId(current != null 2445 ? current.enterpriseConfig : null)); 2446 2447 if (!fromWifiNetworkSuggestion) { 2448 return keyId; 2449 } 2450 return keyId + "_" + trimStringForKeyId(BSSID) + "_" + trimStringForKeyId(creatorName); 2451 } catch (NullPointerException e) { 2452 throw new IllegalStateException("Invalid config details"); 2453 } 2454 } 2455 trimStringForKeyId(String string)2456 private String trimStringForKeyId(String string) { 2457 if (string == null) { 2458 return ""; 2459 } 2460 // Remove quotes and spaces 2461 return string.replace("\"", "").replace(" ", ""); 2462 } 2463 readBitSet(Parcel src)2464 private static BitSet readBitSet(Parcel src) { 2465 int cardinality = src.readInt(); 2466 2467 BitSet set = new BitSet(); 2468 for (int i = 0; i < cardinality; i++) { 2469 set.set(src.readInt()); 2470 } 2471 2472 return set; 2473 } 2474 writeBitSet(Parcel dest, BitSet set)2475 private static void writeBitSet(Parcel dest, BitSet set) { 2476 int nextSetBit = -1; 2477 2478 dest.writeInt(set.cardinality()); 2479 2480 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 2481 dest.writeInt(nextSetBit); 2482 } 2483 } 2484 2485 /** 2486 * Get the authentication type of the network. 2487 * @return One of the {@link KeyMgmt} constants. e.g. {@link KeyMgmt#WPA2_PSK}. 2488 * @hide 2489 */ 2490 @SystemApi 2491 @KeyMgmt.KeyMgmtScheme getAuthType()2492 public int getAuthType() { 2493 if (allowedKeyManagement.cardinality() > 1) { 2494 throw new IllegalStateException("More than one auth type set"); 2495 } 2496 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 2497 return KeyMgmt.WPA_PSK; 2498 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 2499 return KeyMgmt.WPA2_PSK; 2500 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 2501 return KeyMgmt.WPA_EAP; 2502 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 2503 return KeyMgmt.IEEE8021X; 2504 } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { 2505 return KeyMgmt.SAE; 2506 } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { 2507 return KeyMgmt.OWE; 2508 } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { 2509 return KeyMgmt.SUITE_B_192; 2510 } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { 2511 return KeyMgmt.WAPI_PSK; 2512 } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { 2513 return KeyMgmt.WAPI_CERT; 2514 } 2515 return KeyMgmt.NONE; 2516 } 2517 2518 /** 2519 * Return a String that can be used to uniquely identify this WifiConfiguration. 2520 * <br /> 2521 * Note: Do not persist this value! This value is not guaranteed to remain backwards compatible. 2522 */ 2523 @NonNull getKey()2524 public String getKey() { 2525 // Passpoint ephemeral networks have their unique identifier set. Return it as is to be 2526 // able to match internally. 2527 if (mPasspointUniqueId != null) { 2528 return mPasspointUniqueId; 2529 } 2530 2531 String key = getSsidAndSecurityTypeString(); 2532 if (!shared) { 2533 key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier(); 2534 } 2535 2536 return key; 2537 } 2538 2539 /** @hide 2540 * return the SSID + security type in String format. 2541 */ getSsidAndSecurityTypeString()2542 public String getSsidAndSecurityTypeString() { 2543 String key; 2544 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 2545 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 2546 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) 2547 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 2548 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 2549 } else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length 2550 && wepKeys[wepTxKeyIndex] != null) { 2551 key = SSID + "WEP"; 2552 } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { 2553 key = SSID + KeyMgmt.strings[KeyMgmt.OWE]; 2554 } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { 2555 key = SSID + KeyMgmt.strings[KeyMgmt.SAE]; 2556 } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { 2557 key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192]; 2558 } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { 2559 key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_PSK]; 2560 } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { 2561 key = SSID + KeyMgmt.strings[KeyMgmt.WAPI_CERT]; 2562 } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { 2563 key = SSID + KeyMgmt.strings[KeyMgmt.OSEN]; 2564 } else { 2565 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 2566 } 2567 return key; 2568 } 2569 2570 /** 2571 * Get the IpConfiguration object associated with this WifiConfiguration. 2572 * @hide 2573 */ 2574 @NonNull 2575 @SystemApi getIpConfiguration()2576 public IpConfiguration getIpConfiguration() { 2577 return new IpConfiguration(mIpConfiguration); 2578 } 2579 2580 /** 2581 * Set the {@link IpConfiguration} for this network. 2582 * @param ipConfiguration the {@link IpConfiguration} to set, or null to use the default 2583 * constructor {@link IpConfiguration#IpConfiguration()}. 2584 * @hide 2585 */ 2586 @SystemApi setIpConfiguration(@ullable IpConfiguration ipConfiguration)2587 public void setIpConfiguration(@Nullable IpConfiguration ipConfiguration) { 2588 if (ipConfiguration == null) ipConfiguration = new IpConfiguration(); 2589 mIpConfiguration = ipConfiguration; 2590 } 2591 2592 /** 2593 * Get the {@link StaticIpConfiguration} for this network. 2594 * @return the {@link StaticIpConfiguration}, or null if unset. 2595 * @hide 2596 */ 2597 @Nullable 2598 @UnsupportedAppUsage getStaticIpConfiguration()2599 public StaticIpConfiguration getStaticIpConfiguration() { 2600 return mIpConfiguration.getStaticIpConfiguration(); 2601 } 2602 2603 /** @hide */ 2604 @UnsupportedAppUsage setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)2605 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 2606 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 2607 } 2608 2609 /** 2610 * Get the {@link IpConfiguration.IpAssignment} for this network. 2611 * @hide 2612 */ 2613 @NonNull 2614 @UnsupportedAppUsage getIpAssignment()2615 public IpConfiguration.IpAssignment getIpAssignment() { 2616 return mIpConfiguration.getIpAssignment(); 2617 } 2618 2619 /** @hide */ 2620 @UnsupportedAppUsage setIpAssignment(IpConfiguration.IpAssignment ipAssignment)2621 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 2622 mIpConfiguration.setIpAssignment(ipAssignment); 2623 } 2624 2625 /** 2626 * Get the {@link IpConfiguration.ProxySettings} for this network. 2627 * @hide 2628 */ 2629 @NonNull 2630 @UnsupportedAppUsage getProxySettings()2631 public IpConfiguration.ProxySettings getProxySettings() { 2632 return mIpConfiguration.getProxySettings(); 2633 } 2634 2635 /** @hide */ 2636 @UnsupportedAppUsage setProxySettings(IpConfiguration.ProxySettings proxySettings)2637 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 2638 mIpConfiguration.setProxySettings(proxySettings); 2639 } 2640 2641 /** 2642 * Returns the HTTP proxy used by this object. 2643 * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this 2644 * WifiConfiguration, or {@code null} if no proxy is specified. 2645 */ getHttpProxy()2646 public ProxyInfo getHttpProxy() { 2647 if (mIpConfiguration.getProxySettings() == IpConfiguration.ProxySettings.NONE) { 2648 return null; 2649 } 2650 return new ProxyInfo(mIpConfiguration.getHttpProxy()); 2651 } 2652 2653 /** 2654 * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a 2655 * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration} 2656 * with modified proxy settings, the methods {@link WifiManager#addNetwork} and 2657 * {@link WifiManager#updateNetwork} fail and return {@code -1}. 2658 * 2659 * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this 2660 * WifiConfiguration. Setting this to {@code null} will explicitly set no 2661 * proxy, removing any proxy that was previously set. 2662 * @exception IllegalArgumentException for invalid httpProxy 2663 */ setHttpProxy(ProxyInfo httpProxy)2664 public void setHttpProxy(ProxyInfo httpProxy) { 2665 if (httpProxy == null) { 2666 mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); 2667 mIpConfiguration.setHttpProxy(null); 2668 return; 2669 } 2670 ProxyInfo httpProxyCopy; 2671 ProxySettings proxySettingCopy; 2672 if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) { 2673 proxySettingCopy = IpConfiguration.ProxySettings.PAC; 2674 // Construct a new PAC URL Proxy 2675 httpProxyCopy = ProxyInfo.buildPacProxy(httpProxy.getPacFileUrl(), httpProxy.getPort()); 2676 } else { 2677 proxySettingCopy = IpConfiguration.ProxySettings.STATIC; 2678 // Construct a new HTTP Proxy 2679 httpProxyCopy = ProxyInfo.buildDirectProxy(httpProxy.getHost(), httpProxy.getPort(), 2680 Arrays.asList(httpProxy.getExclusionList())); 2681 } 2682 if (!httpProxyCopy.isValid()) { 2683 throw new IllegalArgumentException("Invalid ProxyInfo: " + httpProxyCopy.toString()); 2684 } 2685 mIpConfiguration.setProxySettings(proxySettingCopy); 2686 mIpConfiguration.setHttpProxy(httpProxyCopy); 2687 } 2688 2689 /** 2690 * Set the {@link ProxySettings} and {@link ProxyInfo} for this network. 2691 * @hide 2692 */ 2693 @UnsupportedAppUsage setProxy(@onNull ProxySettings settings, @NonNull ProxyInfo proxy)2694 public void setProxy(@NonNull ProxySettings settings, @NonNull ProxyInfo proxy) { 2695 mIpConfiguration.setProxySettings(settings); 2696 mIpConfiguration.setHttpProxy(proxy); 2697 } 2698 2699 /** Implement the Parcelable interface {@hide} */ describeContents()2700 public int describeContents() { 2701 return 0; 2702 } 2703 2704 /** @hide */ setPasspointManagementObjectTree(String passpointManagementObjectTree)2705 public void setPasspointManagementObjectTree(String passpointManagementObjectTree) { 2706 mPasspointManagementObjectTree = passpointManagementObjectTree; 2707 } 2708 2709 /** @hide */ getMoTree()2710 public String getMoTree() { 2711 return mPasspointManagementObjectTree; 2712 } 2713 2714 /** Copy constructor */ WifiConfiguration(@onNull WifiConfiguration source)2715 public WifiConfiguration(@NonNull WifiConfiguration source) { 2716 if (source != null) { 2717 networkId = source.networkId; 2718 status = source.status; 2719 SSID = source.SSID; 2720 BSSID = source.BSSID; 2721 FQDN = source.FQDN; 2722 roamingConsortiumIds = source.roamingConsortiumIds.clone(); 2723 providerFriendlyName = source.providerFriendlyName; 2724 isHomeProviderNetwork = source.isHomeProviderNetwork; 2725 preSharedKey = source.preSharedKey; 2726 2727 mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus()); 2728 apBand = source.apBand; 2729 apChannel = source.apChannel; 2730 2731 wepKeys = new String[4]; 2732 for (int i = 0; i < wepKeys.length; i++) { 2733 wepKeys[i] = source.wepKeys[i]; 2734 } 2735 2736 wepTxKeyIndex = source.wepTxKeyIndex; 2737 priority = source.priority; 2738 hiddenSSID = source.hiddenSSID; 2739 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 2740 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 2741 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 2742 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 2743 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 2744 allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone(); 2745 allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone(); 2746 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 2747 2748 defaultGwMacAddress = source.defaultGwMacAddress; 2749 2750 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 2751 2752 if ((source.linkedConfigurations != null) 2753 && (source.linkedConfigurations.size() > 0)) { 2754 linkedConfigurations = new HashMap<String, Integer>(); 2755 linkedConfigurations.putAll(source.linkedConfigurations); 2756 } 2757 validatedInternetAccess = source.validatedInternetAccess; 2758 isLegacyPasspointConfig = source.isLegacyPasspointConfig; 2759 ephemeral = source.ephemeral; 2760 osu = source.osu; 2761 trusted = source.trusted; 2762 fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion; 2763 fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier; 2764 meteredHint = source.meteredHint; 2765 meteredOverride = source.meteredOverride; 2766 useExternalScores = source.useExternalScores; 2767 2768 lastConnectUid = source.lastConnectUid; 2769 lastUpdateUid = source.lastUpdateUid; 2770 creatorUid = source.creatorUid; 2771 creatorName = source.creatorName; 2772 lastUpdateName = source.lastUpdateName; 2773 peerWifiConfiguration = source.peerWifiConfiguration; 2774 2775 lastConnected = source.lastConnected; 2776 lastDisconnected = source.lastDisconnected; 2777 numScorerOverride = source.numScorerOverride; 2778 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 2779 numAssociation = source.numAssociation; 2780 allowAutojoin = source.allowAutojoin; 2781 numNoInternetAccessReports = source.numNoInternetAccessReports; 2782 noInternetAccessExpected = source.noInternetAccessExpected; 2783 shared = source.shared; 2784 recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus()); 2785 mRandomizedMacAddress = source.mRandomizedMacAddress; 2786 macRandomizationSetting = source.macRandomizationSetting; 2787 randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs; 2788 requirePmf = source.requirePmf; 2789 updateIdentifier = source.updateIdentifier; 2790 carrierId = source.carrierId; 2791 mPasspointUniqueId = source.mPasspointUniqueId; 2792 } 2793 } 2794 2795 /** Implement the Parcelable interface {@hide} */ 2796 @Override writeToParcel(Parcel dest, int flags)2797 public void writeToParcel(Parcel dest, int flags) { 2798 dest.writeInt(networkId); 2799 dest.writeInt(status); 2800 mNetworkSelectionStatus.writeToParcel(dest); 2801 dest.writeString(SSID); 2802 dest.writeString(BSSID); 2803 dest.writeInt(apBand); 2804 dest.writeInt(apChannel); 2805 dest.writeString(FQDN); 2806 dest.writeString(providerFriendlyName); 2807 dest.writeInt(isHomeProviderNetwork ? 1 : 0); 2808 dest.writeInt(roamingConsortiumIds.length); 2809 for (long roamingConsortiumId : roamingConsortiumIds) { 2810 dest.writeLong(roamingConsortiumId); 2811 } 2812 dest.writeString(preSharedKey); 2813 for (String wepKey : wepKeys) { 2814 dest.writeString(wepKey); 2815 } 2816 dest.writeInt(wepTxKeyIndex); 2817 dest.writeInt(priority); 2818 dest.writeInt(hiddenSSID ? 1 : 0); 2819 dest.writeInt(requirePmf ? 1 : 0); 2820 dest.writeString(updateIdentifier); 2821 2822 writeBitSet(dest, allowedKeyManagement); 2823 writeBitSet(dest, allowedProtocols); 2824 writeBitSet(dest, allowedAuthAlgorithms); 2825 writeBitSet(dest, allowedPairwiseCiphers); 2826 writeBitSet(dest, allowedGroupCiphers); 2827 writeBitSet(dest, allowedGroupManagementCiphers); 2828 writeBitSet(dest, allowedSuiteBCiphers); 2829 2830 dest.writeParcelable(enterpriseConfig, flags); 2831 2832 dest.writeParcelable(mIpConfiguration, flags); 2833 dest.writeString(dhcpServer); 2834 dest.writeString(defaultGwMacAddress); 2835 dest.writeInt(validatedInternetAccess ? 1 : 0); 2836 dest.writeInt(isLegacyPasspointConfig ? 1 : 0); 2837 dest.writeInt(ephemeral ? 1 : 0); 2838 dest.writeInt(trusted ? 1 : 0); 2839 dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0); 2840 dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0); 2841 dest.writeInt(meteredHint ? 1 : 0); 2842 dest.writeInt(meteredOverride); 2843 dest.writeInt(useExternalScores ? 1 : 0); 2844 dest.writeInt(creatorUid); 2845 dest.writeInt(lastConnectUid); 2846 dest.writeInt(lastUpdateUid); 2847 dest.writeString(creatorName); 2848 dest.writeString(lastUpdateName); 2849 dest.writeInt(numScorerOverride); 2850 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 2851 dest.writeInt(numAssociation); 2852 dest.writeBoolean(allowAutojoin); 2853 dest.writeInt(numNoInternetAccessReports); 2854 dest.writeInt(noInternetAccessExpected ? 1 : 0); 2855 dest.writeInt(shared ? 1 : 0); 2856 dest.writeString(mPasspointManagementObjectTree); 2857 dest.writeInt(recentFailure.getAssociationStatus()); 2858 dest.writeParcelable(mRandomizedMacAddress, flags); 2859 dest.writeInt(macRandomizationSetting); 2860 dest.writeInt(osu ? 1 : 0); 2861 dest.writeLong(randomizedMacExpirationTimeMs); 2862 dest.writeInt(carrierId); 2863 dest.writeString(mPasspointUniqueId); 2864 } 2865 2866 /** Implement the Parcelable interface {@hide} */ 2867 @UnsupportedAppUsage 2868 public static final @android.annotation.NonNull Creator<WifiConfiguration> CREATOR = 2869 new Creator<WifiConfiguration>() { 2870 public WifiConfiguration createFromParcel(Parcel in) { 2871 WifiConfiguration config = new WifiConfiguration(); 2872 config.networkId = in.readInt(); 2873 config.status = in.readInt(); 2874 config.mNetworkSelectionStatus.readFromParcel(in); 2875 config.SSID = in.readString(); 2876 config.BSSID = in.readString(); 2877 config.apBand = in.readInt(); 2878 config.apChannel = in.readInt(); 2879 config.FQDN = in.readString(); 2880 config.providerFriendlyName = in.readString(); 2881 config.isHomeProviderNetwork = in.readInt() != 0; 2882 int numRoamingConsortiumIds = in.readInt(); 2883 config.roamingConsortiumIds = new long[numRoamingConsortiumIds]; 2884 for (int i = 0; i < numRoamingConsortiumIds; i++) { 2885 config.roamingConsortiumIds[i] = in.readLong(); 2886 } 2887 config.preSharedKey = in.readString(); 2888 for (int i = 0; i < config.wepKeys.length; i++) { 2889 config.wepKeys[i] = in.readString(); 2890 } 2891 config.wepTxKeyIndex = in.readInt(); 2892 config.priority = in.readInt(); 2893 config.hiddenSSID = in.readInt() != 0; 2894 config.requirePmf = in.readInt() != 0; 2895 config.updateIdentifier = in.readString(); 2896 2897 config.allowedKeyManagement = readBitSet(in); 2898 config.allowedProtocols = readBitSet(in); 2899 config.allowedAuthAlgorithms = readBitSet(in); 2900 config.allowedPairwiseCiphers = readBitSet(in); 2901 config.allowedGroupCiphers = readBitSet(in); 2902 config.allowedGroupManagementCiphers = readBitSet(in); 2903 config.allowedSuiteBCiphers = readBitSet(in); 2904 2905 config.enterpriseConfig = in.readParcelable(null); 2906 config.setIpConfiguration(in.readParcelable(null)); 2907 config.dhcpServer = in.readString(); 2908 config.defaultGwMacAddress = in.readString(); 2909 config.validatedInternetAccess = in.readInt() != 0; 2910 config.isLegacyPasspointConfig = in.readInt() != 0; 2911 config.ephemeral = in.readInt() != 0; 2912 config.trusted = in.readInt() != 0; 2913 config.fromWifiNetworkSuggestion = in.readInt() != 0; 2914 config.fromWifiNetworkSpecifier = in.readInt() != 0; 2915 config.meteredHint = in.readInt() != 0; 2916 config.meteredOverride = in.readInt(); 2917 config.useExternalScores = in.readInt() != 0; 2918 config.creatorUid = in.readInt(); 2919 config.lastConnectUid = in.readInt(); 2920 config.lastUpdateUid = in.readInt(); 2921 config.creatorName = in.readString(); 2922 config.lastUpdateName = in.readString(); 2923 config.numScorerOverride = in.readInt(); 2924 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 2925 config.numAssociation = in.readInt(); 2926 config.allowAutojoin = in.readBoolean(); 2927 config.numNoInternetAccessReports = in.readInt(); 2928 config.noInternetAccessExpected = in.readInt() != 0; 2929 config.shared = in.readInt() != 0; 2930 config.mPasspointManagementObjectTree = in.readString(); 2931 config.recentFailure.setAssociationStatus(in.readInt()); 2932 config.mRandomizedMacAddress = in.readParcelable(null); 2933 config.macRandomizationSetting = in.readInt(); 2934 config.osu = in.readInt() != 0; 2935 config.randomizedMacExpirationTimeMs = in.readLong(); 2936 config.carrierId = in.readInt(); 2937 config.mPasspointUniqueId = in.readString(); 2938 return config; 2939 } 2940 2941 public WifiConfiguration[] newArray(int size) { 2942 return new WifiConfiguration[size]; 2943 } 2944 }; 2945 2946 /** 2947 * Passpoint Unique identifier 2948 * @hide 2949 */ 2950 private String mPasspointUniqueId = null; 2951 2952 /** 2953 * Set the Passpoint unique identifier 2954 * @param uniqueId Passpoint unique identifier to be set 2955 * @hide 2956 */ setPasspointUniqueId(String uniqueId)2957 public void setPasspointUniqueId(String uniqueId) { 2958 mPasspointUniqueId = uniqueId; 2959 } 2960 2961 /** 2962 * Set the Passpoint unique identifier 2963 * @hide 2964 */ getPasspointUniqueId()2965 public String getPasspointUniqueId() { 2966 return mPasspointUniqueId; 2967 } 2968 2969 /** 2970 * If network is one of the most recently connected. 2971 * For framework internal use only. Do not parcel. 2972 * @hide 2973 */ 2974 public boolean isMostRecentlyConnected = false; 2975 2976 /** 2977 * Whether the key mgmt indicates if the WifiConfiguration needs a preSharedKey or not. 2978 * @return true if preSharedKey is needed, false otherwise. 2979 * @hide 2980 */ needsPreSharedKey()2981 public boolean needsPreSharedKey() { 2982 return allowedKeyManagement.get(KeyMgmt.WPA_PSK) 2983 || allowedKeyManagement.get(KeyMgmt.SAE) 2984 || allowedKeyManagement.get(KeyMgmt.WAPI_PSK); 2985 } 2986 2987 } 2988