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.NonNull; 20 import android.annotation.SystemApi; 21 import android.content.pm.PackageManager; 22 import android.net.IpConfiguration; 23 import android.net.IpConfiguration.ProxySettings; 24 import android.net.MacAddress; 25 import android.net.ProxyInfo; 26 import android.net.StaticIpConfiguration; 27 import android.net.Uri; 28 import android.net.wifi.WifiInfo; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 import android.os.SystemClock; 32 import android.os.UserHandle; 33 import android.text.TextUtils; 34 import android.util.BackupUtils; 35 import android.util.Log; 36 import android.util.TimeUtils; 37 38 import java.io.ByteArrayOutputStream; 39 import java.io.DataInputStream; 40 import java.io.DataOutputStream; 41 import java.io.IOException; 42 import java.util.Arrays; 43 import java.util.BitSet; 44 import java.util.HashMap; 45 46 /** 47 * A class representing a configured Wi-Fi network, including the 48 * security configuration. 49 */ 50 public class WifiConfiguration implements Parcelable { 51 private static final String TAG = "WifiConfiguration"; 52 /** 53 * Current Version of the Backup Serializer. 54 */ 55 private static final int BACKUP_VERSION = 2; 56 /** {@hide} */ 57 public static final String ssidVarName = "ssid"; 58 /** {@hide} */ 59 public static final String bssidVarName = "bssid"; 60 /** {@hide} */ 61 public static final String pskVarName = "psk"; 62 /** {@hide} */ 63 @Deprecated 64 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 65 /** {@hide} */ 66 @Deprecated 67 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 68 /** {@hide} */ 69 public static final String priorityVarName = "priority"; 70 /** {@hide} */ 71 public static final String hiddenSSIDVarName = "scan_ssid"; 72 /** {@hide} */ 73 public static final String pmfVarName = "ieee80211w"; 74 /** {@hide} */ 75 public static final String updateIdentiferVarName = "update_identifier"; 76 /** {@hide} */ 77 public static final int INVALID_NETWORK_ID = -1; 78 /** {@hide} */ 79 public static final int LOCAL_ONLY_NETWORK_ID = -2; 80 81 /** {@hide} */ 82 private String mPasspointManagementObjectTree; 83 /** {@hide} */ 84 private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3; 85 86 /** 87 * Recognized key management schemes. 88 */ 89 public static class KeyMgmt { KeyMgmt()90 private KeyMgmt() { } 91 92 /** WPA is not used; plaintext or static WEP could be used. */ 93 public static final int NONE = 0; 94 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 95 public static final int WPA_PSK = 1; 96 /** WPA using EAP authentication. Generally used with an external authentication server. */ 97 public static final int WPA_EAP = 2; 98 /** IEEE 802.1X using EAP authentication and (optionally) dynamically 99 * generated WEP keys. */ 100 public static final int IEEE8021X = 3; 101 102 /** WPA2 pre-shared key for use with soft access point 103 * (requires {@code preSharedKey} to be specified). 104 * @hide 105 */ 106 @SystemApi 107 public static final int WPA2_PSK = 4; 108 /** 109 * Hotspot 2.0 r2 OSEN: 110 * @hide 111 */ 112 public static final int OSEN = 5; 113 114 /** 115 * IEEE 802.11r Fast BSS Transition with PSK authentication. 116 * @hide 117 */ 118 public static final int FT_PSK = 6; 119 120 /** 121 * IEEE 802.11r Fast BSS Transition with EAP authentication. 122 * @hide 123 */ 124 public static final int FT_EAP = 7; 125 126 public static final String varName = "key_mgmt"; 127 128 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", 129 "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" }; 130 } 131 132 /** 133 * Recognized security protocols. 134 */ 135 public static class Protocol { Protocol()136 private Protocol() { } 137 138 /** WPA/IEEE 802.11i/D3.0 139 * @deprecated Due to security and performance limitations, use of WPA-1 networks 140 * is discouraged. WPA-2 (RSN) should be used instead. */ 141 @Deprecated 142 public static final int WPA = 0; 143 /** WPA2/IEEE 802.11i */ 144 public static final int RSN = 1; 145 /** HS2.0 r2 OSEN 146 * @hide 147 */ 148 public static final int OSEN = 2; 149 150 public static final String varName = "proto"; 151 152 public static final String[] strings = { "WPA", "RSN", "OSEN" }; 153 } 154 155 /** 156 * Recognized IEEE 802.11 authentication algorithms. 157 */ 158 public static class AuthAlgorithm { AuthAlgorithm()159 private AuthAlgorithm() { } 160 161 /** Open System authentication (required for WPA/WPA2) */ 162 public static final int OPEN = 0; 163 /** Shared Key authentication (requires static WEP keys) 164 * @deprecated Due to security and performance limitations, use of WEP networks 165 * is discouraged. */ 166 @Deprecated 167 public static final int SHARED = 1; 168 /** LEAP/Network EAP (only used with LEAP) */ 169 public static final int LEAP = 2; 170 171 public static final String varName = "auth_alg"; 172 173 public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; 174 } 175 176 /** 177 * Recognized pairwise ciphers for WPA. 178 */ 179 public static class PairwiseCipher { PairwiseCipher()180 private PairwiseCipher() { } 181 182 /** Use only Group keys (deprecated) */ 183 public static final int NONE = 0; 184 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 185 * @deprecated Due to security and performance limitations, use of WPA-1 networks 186 * is discouraged. WPA-2 (RSN) should be used instead. */ 187 @Deprecated 188 public static final int TKIP = 1; 189 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 190 public static final int CCMP = 2; 191 192 public static final String varName = "pairwise"; 193 194 public static final String[] strings = { "NONE", "TKIP", "CCMP" }; 195 } 196 197 /** 198 * Recognized group ciphers. 199 * <pre> 200 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 201 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 202 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 203 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 204 * </pre> 205 */ 206 public static class GroupCipher { GroupCipher()207 private GroupCipher() { } 208 209 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 210 * @deprecated Due to security and performance limitations, use of WEP networks 211 * is discouraged. */ 212 @Deprecated 213 public static final int WEP40 = 0; 214 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 215 * @deprecated Due to security and performance limitations, use of WEP networks 216 * is discouraged. */ 217 @Deprecated 218 public static final int WEP104 = 1; 219 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 220 public static final int TKIP = 2; 221 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 222 public static final int CCMP = 3; 223 /** Hotspot 2.0 r2 OSEN 224 * @hide 225 */ 226 public static final int GTK_NOT_USED = 4; 227 228 public static final String varName = "group"; 229 230 public static final String[] strings = 231 { /* deprecated */ "WEP40", /* deprecated */ "WEP104", 232 "TKIP", "CCMP", "GTK_NOT_USED" }; 233 } 234 235 /** Possible status of a network configuration. */ 236 public static class Status { Status()237 private Status() { } 238 239 /** this is the network we are currently connected to */ 240 public static final int CURRENT = 0; 241 /** supplicant will not attempt to use this network */ 242 public static final int DISABLED = 1; 243 /** supplicant will consider this network available for association */ 244 public static final int ENABLED = 2; 245 246 public static final String[] strings = { "current", "disabled", "enabled" }; 247 } 248 249 /** @hide */ 250 public static final int UNKNOWN_UID = -1; 251 252 /** 253 * The ID number that the supplicant uses to identify this 254 * network configuration entry. This must be passed as an argument 255 * to most calls into the supplicant. 256 */ 257 public int networkId; 258 259 // Fixme We need remove this field to use only Quality network selection status only 260 /** 261 * The current status of this network configuration entry. 262 * @see Status 263 */ 264 public int status; 265 266 /** 267 * The network's SSID. Can either be a UTF-8 string, 268 * which must be enclosed in double quotation marks 269 * (e.g., {@code "MyNetwork"}), or a string of 270 * hex digits, which are not enclosed in quotes 271 * (e.g., {@code 01a243f405}). 272 */ 273 public String SSID; 274 275 /** 276 * When set, this network configuration entry should only be used when 277 * associating with the AP having the specified BSSID. The value is 278 * a string in the format of an Ethernet MAC address, e.g., 279 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 280 */ 281 public String BSSID; 282 283 /** 284 * 2GHz band. 285 * @hide 286 */ 287 public static final int AP_BAND_2GHZ = 0; 288 289 /** 290 * 5GHz band. 291 * @hide 292 */ 293 public static final int AP_BAND_5GHZ = 1; 294 295 /** 296 * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability, 297 * operating country code and current radio conditions. 298 * @hide 299 */ 300 public static final int AP_BAND_ANY = -1; 301 302 /** 303 * The band which AP resides on 304 * -1:Any 0:2G 1:5G 305 * By default, 2G is chosen 306 * @hide 307 */ 308 public int apBand = AP_BAND_2GHZ; 309 310 /** 311 * The channel which AP resides on,currently, US only 312 * 2G 1-11 313 * 5G 36,40,44,48,149,153,157,161,165 314 * 0 - find a random available channel according to the apBand 315 * @hide 316 */ 317 public int apChannel = 0; 318 319 /** 320 * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in 321 * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or 322 * a string of 64 hex digits for raw PSK. 323 * <p/> 324 * When the value of this key is read, the actual key is 325 * not returned, just a "*" if the key has a value, or the null 326 * string otherwise. 327 */ 328 public String preSharedKey; 329 330 /** 331 * Up to four WEP keys. Either an ASCII string enclosed in double 332 * quotation marks (e.g., {@code "abcdef"}) or a string 333 * of hex digits (e.g., {@code 0102030405}). 334 * <p/> 335 * When the value of one of these keys is read, the actual key is 336 * not returned, just a "*" if the key has a value, or the null 337 * string otherwise. 338 * @deprecated Due to security and performance limitations, use of WEP networks 339 * is discouraged. 340 */ 341 @Deprecated 342 public String[] wepKeys; 343 344 /** Default WEP key index, ranging from 0 to 3. 345 * @deprecated Due to security and performance limitations, use of WEP networks 346 * is discouraged. */ 347 @Deprecated 348 public int wepTxKeyIndex; 349 350 /** 351 * Priority determines the preference given to a network by {@code wpa_supplicant} 352 * when choosing an access point with which to associate. 353 * @deprecated This field does not exist anymore. 354 */ 355 @Deprecated 356 public int priority; 357 358 /** 359 * This is a network that does not broadcast its SSID, so an 360 * SSID-specific probe request must be used for scans. 361 */ 362 public boolean hiddenSSID; 363 364 /** 365 * This is a network that requries Protected Management Frames (PMF). 366 * @hide 367 */ 368 public boolean requirePMF; 369 370 /** 371 * Update identifier, for Passpoint network. 372 * @hide 373 */ 374 public String updateIdentifier; 375 376 /** 377 * The set of key management protocols supported by this configuration. 378 * See {@link KeyMgmt} for descriptions of the values. 379 * Defaults to WPA-PSK WPA-EAP. 380 */ 381 public BitSet allowedKeyManagement; 382 /** 383 * The set of security protocols supported by this configuration. 384 * See {@link Protocol} for descriptions of the values. 385 * Defaults to WPA RSN. 386 */ 387 public BitSet allowedProtocols; 388 /** 389 * The set of authentication protocols supported by this configuration. 390 * See {@link AuthAlgorithm} for descriptions of the values. 391 * Defaults to automatic selection. 392 */ 393 public BitSet allowedAuthAlgorithms; 394 /** 395 * The set of pairwise ciphers for WPA supported by this configuration. 396 * See {@link PairwiseCipher} for descriptions of the values. 397 * Defaults to CCMP TKIP. 398 */ 399 public BitSet allowedPairwiseCiphers; 400 /** 401 * The set of group ciphers supported by this configuration. 402 * See {@link GroupCipher} for descriptions of the values. 403 * Defaults to CCMP TKIP WEP104 WEP40. 404 */ 405 public BitSet allowedGroupCiphers; 406 /** 407 * The enterprise configuration details specifying the EAP method, 408 * certificates and other settings associated with the EAP. 409 */ 410 public WifiEnterpriseConfig enterpriseConfig; 411 412 /** 413 * Fully qualified domain name of a Passpoint configuration 414 */ 415 public String FQDN; 416 417 /** 418 * Name of Passpoint credential provider 419 */ 420 public String providerFriendlyName; 421 422 /** 423 * Flag indicating if this network is provided by a home Passpoint provider or a roaming 424 * Passpoint provider. This flag will be {@code true} if this network is provided by 425 * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider 426 * or is a non-Passpoint network. 427 */ 428 public boolean isHomeProviderNetwork; 429 430 /** 431 * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where 432 * Passpoint credential will be considered valid 433 */ 434 public long[] roamingConsortiumIds; 435 436 /** 437 * @hide 438 * This network configuration is visible to and usable by other users on the 439 * same device. 440 */ 441 public boolean shared; 442 443 /** 444 * @hide 445 */ 446 @NonNull 447 private IpConfiguration mIpConfiguration; 448 449 /** 450 * @hide 451 * dhcp server MAC address if known 452 */ 453 public String dhcpServer; 454 455 /** 456 * @hide 457 * default Gateway MAC address if known 458 */ 459 public String defaultGwMacAddress; 460 461 /** 462 * @hide 463 * last time we connected, this configuration had validated internet access 464 */ 465 public boolean validatedInternetAccess; 466 467 /** 468 * @hide 469 * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM) 470 * This value is populated from scan results that contain Beacon Frames, which are infrequent. 471 * The value is not guaranteed to be set or current (Although it SHOULDNT change once set) 472 * Valid values are from 1 - 255. Initialized here as 0, use this to check if set. 473 */ 474 public int dtimInterval = 0; 475 476 /** 477 * Flag indicating if this configuration represents a legacy Passpoint configuration 478 * (Release N or older). This is used for migrating Passpoint configuration from N to O. 479 * This will no longer be needed after O. 480 * @hide 481 */ 482 public boolean isLegacyPasspointConfig = false; 483 /** 484 * @hide 485 * Uid of app creating the configuration 486 */ 487 @SystemApi 488 public int creatorUid; 489 490 /** 491 * @hide 492 * Uid of last app issuing a connection related command 493 */ 494 public int lastConnectUid; 495 496 /** 497 * @hide 498 * Uid of last app modifying the configuration 499 */ 500 @SystemApi 501 public int lastUpdateUid; 502 503 /** 504 * @hide 505 * Universal name for app creating the configuration 506 * see {#link {@link PackageManager#getNameForUid(int)} 507 */ 508 @SystemApi 509 public String creatorName; 510 511 /** 512 * @hide 513 * Universal name for app updating the configuration 514 * see {#link {@link PackageManager#getNameForUid(int)} 515 */ 516 @SystemApi 517 public String lastUpdateName; 518 519 /** 520 * @hide 521 * Status of user approval for connection 522 */ 523 public int userApproved = USER_UNSPECIFIED; 524 525 /** The Below RSSI thresholds are used to configure AutoJoin 526 * - GOOD/LOW/BAD thresholds are used so as to calculate link score 527 * - UNWANTED_SOFT are used by the blacklisting logic so as to handle 528 * the unwanted network message coming from CS 529 * - UNBLACKLIST thresholds are used so as to tweak the speed at which 530 * the network is unblacklisted (i.e. if 531 * it is seen with good RSSI, it is blacklisted faster) 532 * - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from 533 * the network we need to be before autojoin kicks in 534 */ 535 /** @hide **/ 536 public static int INVALID_RSSI = -127; 537 538 // States for the userApproved field 539 /** 540 * @hide 541 * User hasn't specified if connection is okay 542 */ 543 public static final int USER_UNSPECIFIED = 0; 544 /** 545 * @hide 546 * User has approved this for connection 547 */ 548 public static final int USER_APPROVED = 1; 549 /** 550 * @hide 551 * User has banned this from connection 552 */ 553 public static final int USER_BANNED = 2; 554 /** 555 * @hide 556 * Waiting for user input 557 */ 558 public static final int USER_PENDING = 3; 559 560 /** 561 * @hide 562 * Number of reports indicating no Internet Access 563 */ 564 public int numNoInternetAccessReports; 565 566 /** 567 * @hide 568 * For debug: date at which the config was last updated 569 */ 570 public String updateTime; 571 572 /** 573 * @hide 574 * For debug: date at which the config was last updated 575 */ 576 public String creationTime; 577 578 /** 579 * @hide 580 * The WiFi configuration is considered to have no internet access for purpose of autojoining 581 * if there has been a report of it having no internet access, and, it never have had 582 * internet access in the past. 583 */ 584 @SystemApi hasNoInternetAccess()585 public boolean hasNoInternetAccess() { 586 return numNoInternetAccessReports > 0 && !validatedInternetAccess; 587 } 588 589 /** 590 * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a 591 * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to 592 * this configuration and selects "don't ask again". 593 * @hide 594 */ 595 public boolean noInternetAccessExpected; 596 597 /** 598 * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a 599 * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to 600 * this configuration and selects "don't ask again". 601 * @hide 602 */ 603 @SystemApi isNoInternetAccessExpected()604 public boolean isNoInternetAccessExpected() { 605 return noInternetAccessExpected; 606 } 607 608 /** 609 * @hide 610 * Last time the system was connected to this configuration. 611 */ 612 public long lastConnected; 613 614 /** 615 * @hide 616 * Last time the system was disconnected to this configuration. 617 */ 618 public long lastDisconnected; 619 620 /** 621 * Set if the configuration was self added by the framework 622 * This boolean is cleared if we get a connect/save/ update or 623 * any wifiManager command that indicate the user interacted with the configuration 624 * since we will now consider that the configuration belong to him. 625 * @hide 626 */ 627 public boolean selfAdded; 628 629 /** 630 * Set if the configuration was self added by the framework 631 * This boolean is set once and never cleared. It is used 632 * so as we never loose track of who created the 633 * configuration in the first place. 634 * @hide 635 */ 636 public boolean didSelfAdd; 637 638 /** 639 * Peer WifiConfiguration this WifiConfiguration was added for 640 * @hide 641 */ 642 public String peerWifiConfiguration; 643 644 /** 645 * @hide 646 * Indicate that a WifiConfiguration is temporary and should not be saved 647 * nor considered by AutoJoin. 648 */ 649 public boolean ephemeral; 650 651 /** 652 * @hide 653 * Indicate that a WifiConfiguration is temporary and should not be saved 654 * nor considered by AutoJoin. 655 */ 656 @SystemApi isEphemeral()657 public boolean isEphemeral() { 658 return ephemeral; 659 } 660 661 /** 662 * Indicates if the creator of this configuration has expressed that it 663 * should be considered metered. 664 * 665 * @see #isMetered(WifiConfiguration, WifiInfo) 666 * @hide 667 */ 668 @SystemApi 669 public boolean meteredHint; 670 671 /** {@hide} */ 672 public static final int METERED_OVERRIDE_NONE = 0; 673 /** {@hide} */ 674 public static final int METERED_OVERRIDE_METERED = 1; 675 /** {@hide} */ 676 public static final int METERED_OVERRIDE_NOT_METERED = 2; 677 678 /** 679 * Indicates if the end user has expressed an explicit opinion about the 680 * meteredness of this network, such as through the Settings app. 681 * <p> 682 * This should always override any values from {@link #meteredHint} or 683 * {@link WifiInfo#getMeteredHint()}. 684 * 685 * @see #isMetered(WifiConfiguration, WifiInfo) 686 * @hide 687 */ 688 public int meteredOverride = METERED_OVERRIDE_NONE; 689 690 /** 691 * Blend together all the various opinions to decide if the given network 692 * should be considered metered or not. 693 * 694 * @hide 695 */ isMetered(WifiConfiguration config, WifiInfo info)696 public static boolean isMetered(WifiConfiguration config, WifiInfo info) { 697 boolean metered = false; 698 if (info != null && info.getMeteredHint()) { 699 metered = true; 700 } 701 if (config != null && config.meteredHint) { 702 metered = true; 703 } 704 if (config != null 705 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) { 706 metered = true; 707 } 708 if (config != null 709 && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) { 710 metered = false; 711 } 712 return metered; 713 } 714 715 /** 716 * @hide 717 * Returns true if this WiFi config is for an open network. 718 */ isOpenNetwork()719 public boolean isOpenNetwork() { 720 final int cardinality = allowedKeyManagement.cardinality(); 721 final boolean hasNoKeyMgmt = cardinality == 0 722 || (cardinality == 1 && allowedKeyManagement.get(KeyMgmt.NONE)); 723 724 boolean hasNoWepKeys = true; 725 if (wepKeys != null) { 726 for (int i = 0; i < wepKeys.length; i++) { 727 if (wepKeys[i] != null) { 728 hasNoWepKeys = false; 729 break; 730 } 731 } 732 } 733 734 return hasNoKeyMgmt && hasNoWepKeys; 735 } 736 737 /** 738 * @hide 739 * Setting this value will force scan results associated with this configuration to 740 * be included in the bucket of networks that are externally scored. 741 * If not set, associated scan results will be treated as legacy saved networks and 742 * will take precedence over networks in the scored category. 743 */ 744 @SystemApi 745 public boolean useExternalScores; 746 747 /** 748 * @hide 749 * Number of time the scorer overrode a the priority based choice, when comparing two 750 * WifiConfigurations, note that since comparing WifiConfiguration happens very often 751 * potentially at every scan, this number might become very large, even on an idle 752 * system. 753 */ 754 @SystemApi 755 public int numScorerOverride; 756 757 /** 758 * @hide 759 * Number of time the scorer overrode a the priority based choice, and the comparison 760 * triggered a network switch 761 */ 762 @SystemApi 763 public int numScorerOverrideAndSwitchedNetwork; 764 765 /** 766 * @hide 767 * Number of time we associated to this configuration. 768 */ 769 @SystemApi 770 public int numAssociation; 771 772 /** 773 * @hide 774 * Randomized MAC address to use with this particular network 775 */ 776 @NonNull 777 private MacAddress mRandomizedMacAddress; 778 779 /** 780 * @hide 781 * Checks if the given MAC address can be used for Connected Mac Randomization 782 * by verifying that it is non-null, unicast, locally assigned, and not default mac. 783 * @param mac MacAddress to check 784 * @return true if mac is good to use 785 */ isValidMacAddressForRandomization(MacAddress mac)786 public static boolean isValidMacAddressForRandomization(MacAddress mac) { 787 return mac != null && !mac.isMulticastAddress() && mac.isLocallyAssigned() 788 && !MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS).equals(mac); 789 } 790 791 /** 792 * @hide 793 * Returns Randomized MAC address to use with the network. 794 * If it is not set/valid, creates a new randomized address. 795 * If it can't generate a valid mac, returns the default MAC. 796 */ getOrCreateRandomizedMacAddress()797 public @NonNull MacAddress getOrCreateRandomizedMacAddress() { 798 int randomMacGenerationCount = 0; 799 while (!isValidMacAddressForRandomization(mRandomizedMacAddress) 800 && randomMacGenerationCount < MAXIMUM_RANDOM_MAC_GENERATION_RETRY) { 801 mRandomizedMacAddress = MacAddress.createRandomUnicastAddress(); 802 randomMacGenerationCount++; 803 } 804 805 if (!isValidMacAddressForRandomization(mRandomizedMacAddress)) { 806 mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); 807 } 808 return mRandomizedMacAddress; 809 } 810 811 /** 812 * @hide 813 * Returns MAC address set to be the local randomized MAC address. 814 * Does not guarantee that the returned address is valid for use. 815 */ getRandomizedMacAddress()816 public @NonNull MacAddress getRandomizedMacAddress() { 817 return mRandomizedMacAddress; 818 } 819 820 /** 821 * @hide 822 * @param mac MacAddress to change into 823 */ setRandomizedMacAddress(@onNull MacAddress mac)824 public void setRandomizedMacAddress(@NonNull MacAddress mac) { 825 if (mac == null) { 826 Log.e(TAG, "setRandomizedMacAddress received null MacAddress."); 827 return; 828 } 829 mRandomizedMacAddress = mac; 830 } 831 832 /** @hide 833 * Boost given to RSSI on a home network for the purpose of calculating the score 834 * This adds stickiness to home networks, as defined by: 835 * - less than 4 known BSSIDs 836 * - PSK only 837 * - TODO: add a test to verify that all BSSIDs are behind same gateway 838 ***/ 839 public static final int HOME_NETWORK_RSSI_BOOST = 5; 840 841 /** 842 * @hide 843 * This class is used to contain all the information and API used for quality network selection 844 */ 845 public static class NetworkSelectionStatus { 846 /** 847 * Quality Network Selection Status enable, temporary disabled, permanently disabled 848 */ 849 /** 850 * This network is allowed to join Quality Network Selection 851 */ 852 public static final int NETWORK_SELECTION_ENABLED = 0; 853 /** 854 * network was temporary disabled. Can be re-enabled after a time period expire 855 */ 856 public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; 857 /** 858 * network was permanently disabled. 859 */ 860 public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; 861 /** 862 * Maximum Network selection status 863 */ 864 public static final int NETWORK_SELECTION_STATUS_MAX = 3; 865 866 /** 867 * Quality network selection status String (for debug purpose). Use Quality network 868 * selection status value as index to extec the corresponding debug string 869 */ 870 public static final String[] QUALITY_NETWORK_SELECTION_STATUS = { 871 "NETWORK_SELECTION_ENABLED", 872 "NETWORK_SELECTION_TEMPORARY_DISABLED", 873 "NETWORK_SELECTION_PERMANENTLY_DISABLED"}; 874 875 //Quality Network disabled reasons 876 /** 877 * Default value. Means not disabled 878 */ 879 public static final int NETWORK_SELECTION_ENABLE = 0; 880 /** 881 * The starting index for network selection disabled reasons 882 */ 883 public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1; 884 /** 885 * @deprecated it is not used any more. 886 * This network is disabled because higher layer (>2) network is bad 887 */ 888 public static final int DISABLED_BAD_LINK = 1; 889 /** 890 * This network is disabled because multiple association rejects 891 */ 892 public static final int DISABLED_ASSOCIATION_REJECTION = 2; 893 /** 894 * This network is disabled because multiple authentication failure 895 */ 896 public static final int DISABLED_AUTHENTICATION_FAILURE = 3; 897 /** 898 * This network is disabled because multiple DHCP failure 899 */ 900 public static final int DISABLED_DHCP_FAILURE = 4; 901 /** 902 * This network is disabled because of security network but no credentials 903 */ 904 public static final int DISABLED_DNS_FAILURE = 5; 905 /** 906 * This network is temporarily disabled because it has no Internet access. 907 */ 908 public static final int DISABLED_NO_INTERNET_TEMPORARY = 6; 909 /** 910 * This network is disabled because we started WPS 911 */ 912 public static final int DISABLED_WPS_START = 7; 913 /** 914 * This network is disabled because EAP-TLS failure 915 */ 916 public static final int DISABLED_TLS_VERSION_MISMATCH = 8; 917 // Values above are for temporary disablement; values below are for permanent disablement. 918 /** 919 * This network is disabled due to absence of user credentials 920 */ 921 public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 9; 922 /** 923 * This network is permanently disabled because it has no Internet access and user does not 924 * want to stay connected. 925 */ 926 public static final int DISABLED_NO_INTERNET_PERMANENT = 10; 927 /** 928 * This network is disabled due to WifiManager disable it explicitly 929 */ 930 public static final int DISABLED_BY_WIFI_MANAGER = 11; 931 /** 932 * This network is disabled due to user switching 933 */ 934 public static final int DISABLED_DUE_TO_USER_SWITCH = 12; 935 /** 936 * This network is disabled due to wrong password 937 */ 938 public static final int DISABLED_BY_WRONG_PASSWORD = 13; 939 /** 940 * This Maximum disable reason value 941 */ 942 public static final int NETWORK_SELECTION_DISABLED_MAX = 14; 943 944 /** 945 * Quality network selection disable reason String (for debug purpose) 946 */ 947 public static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = { 948 "NETWORK_SELECTION_ENABLE", 949 "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated 950 "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ", 951 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE", 952 "NETWORK_SELECTION_DISABLED_DHCP_FAILURE", 953 "NETWORK_SELECTION_DISABLED_DNS_FAILURE", 954 "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY", 955 "NETWORK_SELECTION_DISABLED_WPS_START", 956 "NETWORK_SELECTION_DISABLED_TLS_VERSION", 957 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS", 958 "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT", 959 "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER", 960 "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH", 961 "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD" 962 }; 963 964 /** 965 * Invalid time stamp for network selection disable 966 */ 967 public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L; 968 969 /** 970 * This constant indicates the current configuration has connect choice set 971 */ 972 private static final int CONNECT_CHOICE_EXISTS = 1; 973 974 /** 975 * This constant indicates the current configuration does not have connect choice set 976 */ 977 private static final int CONNECT_CHOICE_NOT_EXISTS = -1; 978 979 // fields for QualityNetwork Selection 980 /** 981 * Network selection status, should be in one of three status: enable, temporaily disabled 982 * or permanently disabled 983 */ 984 private int mStatus; 985 986 /** 987 * Reason for disable this network 988 */ 989 private int mNetworkSelectionDisableReason; 990 991 /** 992 * Last time we temporarily disabled the configuration 993 */ 994 private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 995 996 /** 997 * counter for each Network selection disable reason 998 */ 999 private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX]; 1000 1001 /** 1002 * Connect Choice over this configuration 1003 * 1004 * When current wifi configuration is visible to the user but user explicitly choose to 1005 * connect to another network X, the another networks X's configure key will be stored here. 1006 * We will consider user has a preference of X over this network. And in the future, 1007 * network selection will always give X a higher preference over this configuration. 1008 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 1009 */ 1010 private String mConnectChoice; 1011 1012 /** 1013 * The system timestamp when we records the connectChoice. This value is obtained from 1014 * System.currentTimeMillis 1015 */ 1016 private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 1017 1018 /** 1019 * Used to cache the temporary candidate during the network selection procedure. It will be 1020 * kept updating once a new scan result has a higher score than current one 1021 */ 1022 private ScanResult mCandidate; 1023 1024 /** 1025 * Used to cache the score of the current temporary candidate during the network 1026 * selection procedure. 1027 */ 1028 private int mCandidateScore; 1029 1030 /** 1031 * Indicate whether this network is visible in latest Qualified Network Selection. This 1032 * means there is scan result found related to this Configuration and meet the minimum 1033 * requirement. The saved network need not join latest Qualified Network Selection. For 1034 * example, it is disabled. True means network is visible in latest Qualified Network 1035 * Selection and false means network is invisible 1036 */ 1037 private boolean mSeenInLastQualifiedNetworkSelection; 1038 1039 /** 1040 * Boolean indicating if we have ever successfully connected to this network. 1041 * 1042 * This value will be set to true upon a successful connection. 1043 * This value will be set to false if a previous value was not stored in the config or if 1044 * the credentials are updated (ex. a password change). 1045 */ 1046 private boolean mHasEverConnected; 1047 1048 /** 1049 * Boolean indicating whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} 1050 * chose not to connect to this network in the last qualified network selection process. 1051 */ 1052 private boolean mNotRecommended; 1053 1054 /** 1055 * Set whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not 1056 * recommend connecting to this network. 1057 */ setNotRecommended(boolean notRecommended)1058 public void setNotRecommended(boolean notRecommended) { 1059 mNotRecommended = notRecommended; 1060 } 1061 1062 /** 1063 * Returns whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not 1064 * recommend connecting to this network. 1065 */ isNotRecommended()1066 public boolean isNotRecommended() { 1067 return mNotRecommended; 1068 } 1069 1070 /** 1071 * set whether this network is visible in latest Qualified Network Selection 1072 * @param seen value set to candidate 1073 */ setSeenInLastQualifiedNetworkSelection(boolean seen)1074 public void setSeenInLastQualifiedNetworkSelection(boolean seen) { 1075 mSeenInLastQualifiedNetworkSelection = seen; 1076 } 1077 1078 /** 1079 * get whether this network is visible in latest Qualified Network Selection 1080 * @return returns true -- network is visible in latest Qualified Network Selection 1081 * false -- network is invisible in latest Qualified Network Selection 1082 */ getSeenInLastQualifiedNetworkSelection()1083 public boolean getSeenInLastQualifiedNetworkSelection() { 1084 return mSeenInLastQualifiedNetworkSelection; 1085 } 1086 /** 1087 * set the temporary candidate of current network selection procedure 1088 * @param scanCandidate {@link ScanResult} the candidate set to mCandidate 1089 */ setCandidate(ScanResult scanCandidate)1090 public void setCandidate(ScanResult scanCandidate) { 1091 mCandidate = scanCandidate; 1092 } 1093 1094 /** 1095 * get the temporary candidate of current network selection procedure 1096 * @return returns {@link ScanResult} temporary candidate of current network selection 1097 * procedure 1098 */ getCandidate()1099 public ScanResult getCandidate() { 1100 return mCandidate; 1101 } 1102 1103 /** 1104 * set the score of the temporary candidate of current network selection procedure 1105 * @param score value set to mCandidateScore 1106 */ setCandidateScore(int score)1107 public void setCandidateScore(int score) { 1108 mCandidateScore = score; 1109 } 1110 1111 /** 1112 * get the score of the temporary candidate of current network selection procedure 1113 * @return returns score of the temporary candidate of current network selection procedure 1114 */ getCandidateScore()1115 public int getCandidateScore() { 1116 return mCandidateScore; 1117 } 1118 1119 /** 1120 * get user preferred choice over this configuration 1121 *@return returns configKey of user preferred choice over this configuration 1122 */ getConnectChoice()1123 public String getConnectChoice() { 1124 return mConnectChoice; 1125 } 1126 1127 /** 1128 * set user preferred choice over this configuration 1129 * @param newConnectChoice, the configKey of user preferred choice over this configuration 1130 */ setConnectChoice(String newConnectChoice)1131 public void setConnectChoice(String newConnectChoice) { 1132 mConnectChoice = newConnectChoice; 1133 } 1134 1135 /** 1136 * get the timeStamp when user select a choice over this configuration 1137 * @return returns when current connectChoice is set (time from System.currentTimeMillis) 1138 */ getConnectChoiceTimestamp()1139 public long getConnectChoiceTimestamp() { 1140 return mConnectChoiceTimestamp; 1141 } 1142 1143 /** 1144 * set the timeStamp when user select a choice over this configuration 1145 * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should 1146 * be obtained from System.currentTimeMillis 1147 */ setConnectChoiceTimestamp(long timeStamp)1148 public void setConnectChoiceTimestamp(long timeStamp) { 1149 mConnectChoiceTimestamp = timeStamp; 1150 } 1151 1152 /** 1153 * get current Quality network selection status 1154 * @return returns current Quality network selection status in String (for debug purpose) 1155 */ getNetworkStatusString()1156 public String getNetworkStatusString() { 1157 return QUALITY_NETWORK_SELECTION_STATUS[mStatus]; 1158 } 1159 setHasEverConnected(boolean value)1160 public void setHasEverConnected(boolean value) { 1161 mHasEverConnected = value; 1162 } 1163 getHasEverConnected()1164 public boolean getHasEverConnected() { 1165 return mHasEverConnected; 1166 } 1167 NetworkSelectionStatus()1168 public NetworkSelectionStatus() { 1169 // previously stored configs will not have this parameter, so we default to false. 1170 mHasEverConnected = false; 1171 }; 1172 1173 /** 1174 * @param reason specific error reason 1175 * @return corresponding network disable reason String (for debug purpose) 1176 */ getNetworkDisableReasonString(int reason)1177 public static String getNetworkDisableReasonString(int reason) { 1178 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1179 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[reason]; 1180 } else { 1181 return null; 1182 } 1183 } 1184 /** 1185 * get current network disable reason 1186 * @return current network disable reason in String (for debug purpose) 1187 */ getNetworkDisableReasonString()1188 public String getNetworkDisableReasonString() { 1189 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[mNetworkSelectionDisableReason]; 1190 } 1191 1192 /** 1193 * get current network network selection status 1194 * @return return current network network selection status 1195 */ getNetworkSelectionStatus()1196 public int getNetworkSelectionStatus() { 1197 return mStatus; 1198 } 1199 /** 1200 * @return whether current network is enabled to join network selection 1201 */ isNetworkEnabled()1202 public boolean isNetworkEnabled() { 1203 return mStatus == NETWORK_SELECTION_ENABLED; 1204 } 1205 1206 /** 1207 * @return whether current network is temporary disabled 1208 */ isNetworkTemporaryDisabled()1209 public boolean isNetworkTemporaryDisabled() { 1210 return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED; 1211 } 1212 1213 /** 1214 * @return returns whether current network is permanently disabled 1215 */ isNetworkPermanentlyDisabled()1216 public boolean isNetworkPermanentlyDisabled() { 1217 return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED; 1218 } 1219 1220 /** 1221 * set current networ work selection status 1222 * @param status network selection status to set 1223 */ setNetworkSelectionStatus(int status)1224 public void setNetworkSelectionStatus(int status) { 1225 if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) { 1226 mStatus = status; 1227 } 1228 } 1229 1230 /** 1231 * @return returns current network's disable reason 1232 */ getNetworkSelectionDisableReason()1233 public int getNetworkSelectionDisableReason() { 1234 return mNetworkSelectionDisableReason; 1235 } 1236 1237 /** 1238 * set Network disable reason 1239 * @param reason Network disable reason 1240 */ setNetworkSelectionDisableReason(int reason)1241 public void setNetworkSelectionDisableReason(int reason) { 1242 if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) { 1243 mNetworkSelectionDisableReason = reason; 1244 } else { 1245 throw new IllegalArgumentException("Illegal reason value: " + reason); 1246 } 1247 } 1248 1249 /** 1250 * check whether network is disabled by this reason 1251 * @param reason a specific disable reason 1252 * @return true -- network is disabled for this reason 1253 * false -- network is not disabled for this reason 1254 */ isDisabledByReason(int reason)1255 public boolean isDisabledByReason(int reason) { 1256 return mNetworkSelectionDisableReason == reason; 1257 } 1258 1259 /** 1260 * @param timeStamp Set when current network is disabled in millisecond since January 1, 1261 * 1970 00:00:00.0 UTC 1262 */ setDisableTime(long timeStamp)1263 public void setDisableTime(long timeStamp) { 1264 mTemporarilyDisabledTimestamp = timeStamp; 1265 } 1266 1267 /** 1268 * @return returns when current network is disabled in millisecond since January 1, 1269 * 1970 00:00:00.0 UTC 1270 */ getDisableTime()1271 public long getDisableTime() { 1272 return mTemporarilyDisabledTimestamp; 1273 } 1274 1275 /** 1276 * get the disable counter of a specific reason 1277 * @param reason specific failure reason 1278 * @exception throw IllegalArgumentException for illegal input 1279 * @return counter number for specific error reason. 1280 */ getDisableReasonCounter(int reason)1281 public int getDisableReasonCounter(int reason) { 1282 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1283 return mNetworkSeclectionDisableCounter[reason]; 1284 } else { 1285 throw new IllegalArgumentException("Illegal reason value: " + reason); 1286 } 1287 } 1288 1289 /** 1290 * set the counter of a specific failure reason 1291 * @param reason reason for disable error 1292 * @param value the counter value for this specific reason 1293 * @exception throw IllegalArgumentException for illegal input 1294 */ setDisableReasonCounter(int reason, int value)1295 public void setDisableReasonCounter(int reason, int value) { 1296 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1297 mNetworkSeclectionDisableCounter[reason] = value; 1298 } else { 1299 throw new IllegalArgumentException("Illegal reason value: " + reason); 1300 } 1301 } 1302 1303 /** 1304 * increment the counter of a specific failure reason 1305 * @param reason a specific failure reason 1306 * @exception throw IllegalArgumentException for illegal input 1307 */ incrementDisableReasonCounter(int reason)1308 public void incrementDisableReasonCounter(int reason) { 1309 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1310 mNetworkSeclectionDisableCounter[reason]++; 1311 } else { 1312 throw new IllegalArgumentException("Illegal reason value: " + reason); 1313 } 1314 } 1315 1316 /** 1317 * clear the counter of a specific failure reason 1318 * @hide 1319 * @param reason a specific failure reason 1320 * @exception throw IllegalArgumentException for illegal input 1321 */ clearDisableReasonCounter(int reason)1322 public void clearDisableReasonCounter(int reason) { 1323 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1324 mNetworkSeclectionDisableCounter[reason] = NETWORK_SELECTION_ENABLE; 1325 } else { 1326 throw new IllegalArgumentException("Illegal reason value: " + reason); 1327 } 1328 } 1329 1330 /** 1331 * clear all the failure reason counters 1332 */ clearDisableReasonCounter()1333 public void clearDisableReasonCounter() { 1334 Arrays.fill(mNetworkSeclectionDisableCounter, NETWORK_SELECTION_ENABLE); 1335 } 1336 1337 /** 1338 * BSSID for connection to this network (through network selection procedure) 1339 */ 1340 private String mNetworkSelectionBSSID; 1341 1342 /** 1343 * get current network Selection BSSID 1344 * @return current network Selection BSSID 1345 */ getNetworkSelectionBSSID()1346 public String getNetworkSelectionBSSID() { 1347 return mNetworkSelectionBSSID; 1348 } 1349 1350 /** 1351 * set network Selection BSSID 1352 * @param bssid The target BSSID for assocaition 1353 */ setNetworkSelectionBSSID(String bssid)1354 public void setNetworkSelectionBSSID(String bssid) { 1355 mNetworkSelectionBSSID = bssid; 1356 } 1357 copy(NetworkSelectionStatus source)1358 public void copy(NetworkSelectionStatus source) { 1359 mStatus = source.mStatus; 1360 mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason; 1361 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1362 index++) { 1363 mNetworkSeclectionDisableCounter[index] = 1364 source.mNetworkSeclectionDisableCounter[index]; 1365 } 1366 mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp; 1367 mNetworkSelectionBSSID = source.mNetworkSelectionBSSID; 1368 setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection()); 1369 setCandidate(source.getCandidate()); 1370 setCandidateScore(source.getCandidateScore()); 1371 setConnectChoice(source.getConnectChoice()); 1372 setConnectChoiceTimestamp(source.getConnectChoiceTimestamp()); 1373 setHasEverConnected(source.getHasEverConnected()); 1374 setNotRecommended(source.isNotRecommended()); 1375 } 1376 writeToParcel(Parcel dest)1377 public void writeToParcel(Parcel dest) { 1378 dest.writeInt(getNetworkSelectionStatus()); 1379 dest.writeInt(getNetworkSelectionDisableReason()); 1380 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1381 index++) { 1382 dest.writeInt(getDisableReasonCounter(index)); 1383 } 1384 dest.writeLong(getDisableTime()); 1385 dest.writeString(getNetworkSelectionBSSID()); 1386 if (getConnectChoice() != null) { 1387 dest.writeInt(CONNECT_CHOICE_EXISTS); 1388 dest.writeString(getConnectChoice()); 1389 dest.writeLong(getConnectChoiceTimestamp()); 1390 } else { 1391 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); 1392 } 1393 dest.writeInt(getHasEverConnected() ? 1 : 0); 1394 dest.writeInt(isNotRecommended() ? 1 : 0); 1395 } 1396 readFromParcel(Parcel in)1397 public void readFromParcel(Parcel in) { 1398 setNetworkSelectionStatus(in.readInt()); 1399 setNetworkSelectionDisableReason(in.readInt()); 1400 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1401 index++) { 1402 setDisableReasonCounter(index, in.readInt()); 1403 } 1404 setDisableTime(in.readLong()); 1405 setNetworkSelectionBSSID(in.readString()); 1406 if (in.readInt() == CONNECT_CHOICE_EXISTS) { 1407 setConnectChoice(in.readString()); 1408 setConnectChoiceTimestamp(in.readLong()); 1409 } else { 1410 setConnectChoice(null); 1411 setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); 1412 } 1413 setHasEverConnected(in.readInt() != 0); 1414 setNotRecommended(in.readInt() != 0); 1415 } 1416 } 1417 1418 /** 1419 * @hide 1420 * network selection related member 1421 */ 1422 private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus(); 1423 1424 /** 1425 * @hide 1426 * This class is intended to store extra failure reason information for the most recent 1427 * connection attempt, so that it may be surfaced to the settings UI 1428 */ 1429 public static class RecentFailure { 1430 1431 /** 1432 * No recent failure, or no specific reason given for the recent connection failure 1433 */ 1434 public static final int NONE = 0; 1435 /** 1436 * Connection to this network recently failed due to Association Rejection Status 17 1437 * (AP is full) 1438 */ 1439 public static final int STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17; 1440 /** 1441 * Association Rejection Status code (NONE for success/non-association-rejection-fail) 1442 */ 1443 private int mAssociationStatus = NONE; 1444 1445 /** 1446 * @param status the association status code for the recent failure 1447 */ setAssociationStatus(int status)1448 public void setAssociationStatus(int status) { 1449 mAssociationStatus = status; 1450 } 1451 /** 1452 * Sets the RecentFailure to NONE 1453 */ clear()1454 public void clear() { 1455 mAssociationStatus = NONE; 1456 } 1457 /** 1458 * Get the recent failure code 1459 */ getAssociationStatus()1460 public int getAssociationStatus() { 1461 return mAssociationStatus; 1462 } 1463 } 1464 1465 /** 1466 * @hide 1467 * RecentFailure member 1468 */ 1469 final public RecentFailure recentFailure = new RecentFailure(); 1470 1471 /** 1472 * @hide 1473 * @return network selection status 1474 */ getNetworkSelectionStatus()1475 public NetworkSelectionStatus getNetworkSelectionStatus() { 1476 return mNetworkSelectionStatus; 1477 } 1478 1479 /** 1480 * Set the network selection status 1481 * @hide 1482 */ setNetworkSelectionStatus(NetworkSelectionStatus status)1483 public void setNetworkSelectionStatus(NetworkSelectionStatus status) { 1484 mNetworkSelectionStatus = status; 1485 } 1486 1487 /** 1488 * @hide 1489 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 1490 * regarding roaming and auto-joining. 1491 * The linked configuration may or may not have same SSID, and may or may not have same 1492 * credentials. 1493 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 1494 */ 1495 public HashMap<String, Integer> linkedConfigurations; 1496 WifiConfiguration()1497 public WifiConfiguration() { 1498 networkId = INVALID_NETWORK_ID; 1499 SSID = null; 1500 BSSID = null; 1501 FQDN = null; 1502 roamingConsortiumIds = new long[0]; 1503 priority = 0; 1504 hiddenSSID = false; 1505 allowedKeyManagement = new BitSet(); 1506 allowedProtocols = new BitSet(); 1507 allowedAuthAlgorithms = new BitSet(); 1508 allowedPairwiseCiphers = new BitSet(); 1509 allowedGroupCiphers = new BitSet(); 1510 wepKeys = new String[4]; 1511 for (int i = 0; i < wepKeys.length; i++) { 1512 wepKeys[i] = null; 1513 } 1514 enterpriseConfig = new WifiEnterpriseConfig(); 1515 selfAdded = false; 1516 didSelfAdd = false; 1517 ephemeral = false; 1518 meteredHint = false; 1519 meteredOverride = METERED_OVERRIDE_NONE; 1520 useExternalScores = false; 1521 validatedInternetAccess = false; 1522 mIpConfiguration = new IpConfiguration(); 1523 lastUpdateUid = -1; 1524 creatorUid = -1; 1525 shared = true; 1526 dtimInterval = 0; 1527 mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); 1528 } 1529 1530 /** 1531 * Identify if this configuration represents a Passpoint network 1532 */ isPasspoint()1533 public boolean isPasspoint() { 1534 return !TextUtils.isEmpty(FQDN) 1535 && !TextUtils.isEmpty(providerFriendlyName) 1536 && enterpriseConfig != null 1537 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 1538 } 1539 1540 /** 1541 * Helper function, identify if a configuration is linked 1542 * @hide 1543 */ isLinked(WifiConfiguration config)1544 public boolean isLinked(WifiConfiguration config) { 1545 if (config != null) { 1546 if (config.linkedConfigurations != null && linkedConfigurations != null) { 1547 if (config.linkedConfigurations.get(configKey()) != null 1548 && linkedConfigurations.get(config.configKey()) != null) { 1549 return true; 1550 } 1551 } 1552 } 1553 return false; 1554 } 1555 1556 /** 1557 * Helper function, idenfity if a configuration should be treated as an enterprise network 1558 * @hide 1559 */ isEnterprise()1560 public boolean isEnterprise() { 1561 return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) 1562 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) 1563 && enterpriseConfig != null 1564 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 1565 } 1566 1567 @Override toString()1568 public String toString() { 1569 StringBuilder sbuf = new StringBuilder(); 1570 if (this.status == WifiConfiguration.Status.CURRENT) { 1571 sbuf.append("* "); 1572 } else if (this.status == WifiConfiguration.Status.DISABLED) { 1573 sbuf.append("- DSBLE "); 1574 } 1575 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 1576 append(" PROVIDER-NAME: ").append(this.providerFriendlyName). 1577 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN) 1578 .append(" PRIO: ").append(this.priority) 1579 .append(" HIDDEN: ").append(this.hiddenSSID) 1580 .append('\n'); 1581 1582 1583 sbuf.append(" NetworkSelectionStatus ") 1584 .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n"); 1585 if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) { 1586 sbuf.append(" mNetworkSelectionDisableReason ") 1587 .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n"); 1588 1589 for (int index = mNetworkSelectionStatus.NETWORK_SELECTION_ENABLE; 1590 index < mNetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) { 1591 if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) { 1592 sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index) 1593 + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index) 1594 + "\n"); 1595 } 1596 } 1597 } 1598 if (mNetworkSelectionStatus.getConnectChoice() != null) { 1599 sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); 1600 sbuf.append(" connect choice set time: ") 1601 .append(TimeUtils.logTimeOfDay( 1602 mNetworkSelectionStatus.getConnectChoiceTimestamp())); 1603 } 1604 sbuf.append(" hasEverConnected: ") 1605 .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n"); 1606 1607 if (this.numAssociation > 0) { 1608 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 1609 } 1610 if (this.numNoInternetAccessReports > 0) { 1611 sbuf.append(" numNoInternetAccessReports "); 1612 sbuf.append(this.numNoInternetAccessReports).append("\n"); 1613 } 1614 if (this.updateTime != null) { 1615 sbuf.append(" update ").append(this.updateTime).append("\n"); 1616 } 1617 if (this.creationTime != null) { 1618 sbuf.append(" creation ").append(this.creationTime).append("\n"); 1619 } 1620 if (this.didSelfAdd) sbuf.append(" didSelfAdd"); 1621 if (this.selfAdded) sbuf.append(" selfAdded"); 1622 if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); 1623 if (this.ephemeral) sbuf.append(" ephemeral"); 1624 if (this.meteredHint) sbuf.append(" meteredHint"); 1625 if (this.useExternalScores) sbuf.append(" useExternalScores"); 1626 if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess 1627 || this.ephemeral || this.meteredHint || this.useExternalScores) { 1628 sbuf.append("\n"); 1629 } 1630 if (this.meteredOverride != METERED_OVERRIDE_NONE) { 1631 sbuf.append(" meteredOverride ").append(meteredOverride).append("\n"); 1632 } 1633 sbuf.append(" KeyMgmt:"); 1634 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 1635 if (this.allowedKeyManagement.get(k)) { 1636 sbuf.append(" "); 1637 if (k < KeyMgmt.strings.length) { 1638 sbuf.append(KeyMgmt.strings[k]); 1639 } else { 1640 sbuf.append("??"); 1641 } 1642 } 1643 } 1644 sbuf.append(" Protocols:"); 1645 for (int p = 0; p < this.allowedProtocols.size(); p++) { 1646 if (this.allowedProtocols.get(p)) { 1647 sbuf.append(" "); 1648 if (p < Protocol.strings.length) { 1649 sbuf.append(Protocol.strings[p]); 1650 } else { 1651 sbuf.append("??"); 1652 } 1653 } 1654 } 1655 sbuf.append('\n'); 1656 sbuf.append(" AuthAlgorithms:"); 1657 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 1658 if (this.allowedAuthAlgorithms.get(a)) { 1659 sbuf.append(" "); 1660 if (a < AuthAlgorithm.strings.length) { 1661 sbuf.append(AuthAlgorithm.strings[a]); 1662 } else { 1663 sbuf.append("??"); 1664 } 1665 } 1666 } 1667 sbuf.append('\n'); 1668 sbuf.append(" PairwiseCiphers:"); 1669 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 1670 if (this.allowedPairwiseCiphers.get(pc)) { 1671 sbuf.append(" "); 1672 if (pc < PairwiseCipher.strings.length) { 1673 sbuf.append(PairwiseCipher.strings[pc]); 1674 } else { 1675 sbuf.append("??"); 1676 } 1677 } 1678 } 1679 sbuf.append('\n'); 1680 sbuf.append(" GroupCiphers:"); 1681 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 1682 if (this.allowedGroupCiphers.get(gc)) { 1683 sbuf.append(" "); 1684 if (gc < GroupCipher.strings.length) { 1685 sbuf.append(GroupCipher.strings[gc]); 1686 } else { 1687 sbuf.append("??"); 1688 } 1689 } 1690 } 1691 sbuf.append('\n').append(" PSK: "); 1692 if (this.preSharedKey != null) { 1693 sbuf.append('*'); 1694 } 1695 sbuf.append("\nEnterprise config:\n"); 1696 sbuf.append(enterpriseConfig); 1697 1698 sbuf.append("IP config:\n"); 1699 sbuf.append(mIpConfiguration.toString()); 1700 1701 if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) { 1702 sbuf.append(" networkSelectionBSSID=" 1703 + mNetworkSelectionStatus.getNetworkSelectionBSSID()); 1704 } 1705 long now_ms = SystemClock.elapsedRealtime(); 1706 if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus 1707 .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) { 1708 sbuf.append('\n'); 1709 long diff = now_ms - mNetworkSelectionStatus.getDisableTime(); 1710 if (diff <= 0) { 1711 sbuf.append(" blackListed since <incorrect>"); 1712 } else { 1713 sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec "); 1714 } 1715 } 1716 if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid); 1717 if (creatorName != null) sbuf.append(" cname=" + creatorName); 1718 if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid); 1719 if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName); 1720 sbuf.append(" lcuid=" + lastConnectUid); 1721 sbuf.append(" userApproved=" + userApprovedAsString(userApproved)); 1722 sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected); 1723 sbuf.append(" "); 1724 1725 if (this.lastConnected != 0) { 1726 sbuf.append('\n'); 1727 sbuf.append("lastConnected: ").append(TimeUtils.logTimeOfDay(this.lastConnected)); 1728 sbuf.append(" "); 1729 } 1730 sbuf.append('\n'); 1731 if (this.linkedConfigurations != null) { 1732 for (String key : this.linkedConfigurations.keySet()) { 1733 sbuf.append(" linked: ").append(key); 1734 sbuf.append('\n'); 1735 } 1736 } 1737 sbuf.append("recentFailure: ").append("Association Rejection code: ") 1738 .append(recentFailure.getAssociationStatus()).append("\n"); 1739 return sbuf.toString(); 1740 } 1741 1742 /** {@hide} */ getPrintableSsid()1743 public String getPrintableSsid() { 1744 if (SSID == null) return ""; 1745 final int length = SSID.length(); 1746 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 1747 return SSID.substring(1, length - 1); 1748 } 1749 1750 /** The ascii-encoded string format is P"<ascii-encoded-string>" 1751 * The decoding is implemented in the supplicant for a newly configured 1752 * network. 1753 */ 1754 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 1755 (SSID.charAt(length-1) == '"')) { 1756 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 1757 SSID.substring(2, length - 1)); 1758 return wifiSsid.toString(); 1759 } 1760 return SSID; 1761 } 1762 1763 /** @hide **/ userApprovedAsString(int userApproved)1764 public static String userApprovedAsString(int userApproved) { 1765 switch (userApproved) { 1766 case USER_APPROVED: 1767 return "USER_APPROVED"; 1768 case USER_BANNED: 1769 return "USER_BANNED"; 1770 case USER_UNSPECIFIED: 1771 return "USER_UNSPECIFIED"; 1772 default: 1773 return "INVALID"; 1774 } 1775 } 1776 1777 /** 1778 * Get an identifier for associating credentials with this config 1779 * @param current configuration contains values for additional fields 1780 * that are not part of this configuration. Used 1781 * when a config with some fields is passed by an application. 1782 * @throws IllegalStateException if config is invalid for key id generation 1783 * @hide 1784 */ getKeyIdForCredentials(WifiConfiguration current)1785 public String getKeyIdForCredentials(WifiConfiguration current) { 1786 String keyMgmt = null; 1787 1788 try { 1789 // Get current config details for fields that are not initialized 1790 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 1791 if (allowedKeyManagement.cardinality() == 0) { 1792 allowedKeyManagement = current.allowedKeyManagement; 1793 } 1794 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1795 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1796 } 1797 if (allowedKeyManagement.get(KeyMgmt.OSEN)) { 1798 keyMgmt = KeyMgmt.strings[KeyMgmt.OSEN]; 1799 } 1800 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1801 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 1802 } 1803 1804 if (TextUtils.isEmpty(keyMgmt)) { 1805 throw new IllegalStateException("Not an EAP network"); 1806 } 1807 1808 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 1809 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 1810 current.enterpriseConfig : null)); 1811 } catch (NullPointerException e) { 1812 throw new IllegalStateException("Invalid config details"); 1813 } 1814 } 1815 trimStringForKeyId(String string)1816 private String trimStringForKeyId(String string) { 1817 // Remove quotes and spaces 1818 return string.replace("\"", "").replace(" ", ""); 1819 } 1820 readBitSet(Parcel src)1821 private static BitSet readBitSet(Parcel src) { 1822 int cardinality = src.readInt(); 1823 1824 BitSet set = new BitSet(); 1825 for (int i = 0; i < cardinality; i++) { 1826 set.set(src.readInt()); 1827 } 1828 1829 return set; 1830 } 1831 writeBitSet(Parcel dest, BitSet set)1832 private static void writeBitSet(Parcel dest, BitSet set) { 1833 int nextSetBit = -1; 1834 1835 dest.writeInt(set.cardinality()); 1836 1837 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1838 dest.writeInt(nextSetBit); 1839 } 1840 } 1841 1842 /** @hide */ getAuthType()1843 public int getAuthType() { 1844 if (allowedKeyManagement.cardinality() > 1) { 1845 throw new IllegalStateException("More than one auth type set"); 1846 } 1847 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1848 return KeyMgmt.WPA_PSK; 1849 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 1850 return KeyMgmt.WPA2_PSK; 1851 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1852 return KeyMgmt.WPA_EAP; 1853 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1854 return KeyMgmt.IEEE8021X; 1855 } 1856 return KeyMgmt.NONE; 1857 } 1858 1859 /* @hide 1860 * Cache the config key, this seems useful as a speed up since a lot of 1861 * lookups in the config store are done and based on this key. 1862 */ 1863 String mCachedConfigKey; 1864 1865 /** @hide 1866 * return the string used to calculate the hash in WifiConfigStore 1867 * and uniquely identify this WifiConfiguration 1868 */ configKey(boolean allowCached)1869 public String configKey(boolean allowCached) { 1870 String key; 1871 if (allowCached && mCachedConfigKey != null) { 1872 key = mCachedConfigKey; 1873 } else if (providerFriendlyName != null) { 1874 key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1875 if (!shared) { 1876 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); 1877 } 1878 } else { 1879 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1880 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1881 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1882 allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1883 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1884 } else if (wepKeys[0] != null) { 1885 key = SSID + "WEP"; 1886 } else { 1887 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1888 } 1889 if (!shared) { 1890 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); 1891 } 1892 mCachedConfigKey = key; 1893 } 1894 return key; 1895 } 1896 1897 /** @hide 1898 * get configKey, force calculating the config string 1899 */ configKey()1900 public String configKey() { 1901 return configKey(false); 1902 } 1903 1904 /** @hide */ getIpConfiguration()1905 public IpConfiguration getIpConfiguration() { 1906 return mIpConfiguration; 1907 } 1908 1909 /** @hide */ setIpConfiguration(IpConfiguration ipConfiguration)1910 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1911 if (ipConfiguration == null) ipConfiguration = new IpConfiguration(); 1912 mIpConfiguration = ipConfiguration; 1913 } 1914 1915 /** @hide */ getStaticIpConfiguration()1916 public StaticIpConfiguration getStaticIpConfiguration() { 1917 return mIpConfiguration.getStaticIpConfiguration(); 1918 } 1919 1920 /** @hide */ setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)1921 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 1922 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 1923 } 1924 1925 /** @hide */ getIpAssignment()1926 public IpConfiguration.IpAssignment getIpAssignment() { 1927 return mIpConfiguration.ipAssignment; 1928 } 1929 1930 /** @hide */ setIpAssignment(IpConfiguration.IpAssignment ipAssignment)1931 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1932 mIpConfiguration.ipAssignment = ipAssignment; 1933 } 1934 1935 /** @hide */ getProxySettings()1936 public IpConfiguration.ProxySettings getProxySettings() { 1937 return mIpConfiguration.proxySettings; 1938 } 1939 1940 /** @hide */ setProxySettings(IpConfiguration.ProxySettings proxySettings)1941 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1942 mIpConfiguration.proxySettings = proxySettings; 1943 } 1944 1945 /** 1946 * Returns the HTTP proxy used by this object. 1947 * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this 1948 * WifiConfiguration, or {@code null} if no proxy is specified. 1949 */ getHttpProxy()1950 public ProxyInfo getHttpProxy() { 1951 if (mIpConfiguration.proxySettings == IpConfiguration.ProxySettings.NONE) { 1952 return null; 1953 } 1954 return new ProxyInfo(mIpConfiguration.httpProxy); 1955 } 1956 1957 /** 1958 * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a 1959 * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration} 1960 * with modified proxy settings, the methods {@link WifiManager#addNetwork} and 1961 * {@link WifiManager#updateNetwork} fail and return {@code -1}. 1962 * 1963 * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this 1964 * WifiConfiguration. Setting this to {@code null} will explicitly set no 1965 * proxy, removing any proxy that was previously set. 1966 * @exception IllegalArgumentException for invalid httpProxy 1967 */ setHttpProxy(ProxyInfo httpProxy)1968 public void setHttpProxy(ProxyInfo httpProxy) { 1969 if (httpProxy == null) { 1970 mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); 1971 mIpConfiguration.setHttpProxy(null); 1972 return; 1973 } 1974 ProxyInfo httpProxyCopy; 1975 ProxySettings proxySettingCopy; 1976 if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) { 1977 proxySettingCopy = IpConfiguration.ProxySettings.PAC; 1978 // Construct a new PAC URL Proxy 1979 httpProxyCopy = new ProxyInfo(httpProxy.getPacFileUrl(), httpProxy.getPort()); 1980 } else { 1981 proxySettingCopy = IpConfiguration.ProxySettings.STATIC; 1982 // Construct a new HTTP Proxy 1983 httpProxyCopy = new ProxyInfo(httpProxy.getHost(), httpProxy.getPort(), 1984 httpProxy.getExclusionListAsString()); 1985 } 1986 if (!httpProxyCopy.isValid()) { 1987 throw new IllegalArgumentException("Invalid ProxyInfo: " + httpProxyCopy.toString()); 1988 } 1989 mIpConfiguration.setProxySettings(proxySettingCopy); 1990 mIpConfiguration.setHttpProxy(httpProxyCopy); 1991 } 1992 1993 /** @hide */ setProxy(ProxySettings settings, ProxyInfo proxy)1994 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1995 mIpConfiguration.proxySettings = settings; 1996 mIpConfiguration.httpProxy = proxy; 1997 } 1998 1999 /** Implement the Parcelable interface {@hide} */ describeContents()2000 public int describeContents() { 2001 return 0; 2002 } 2003 2004 /** @hide */ setPasspointManagementObjectTree(String passpointManagementObjectTree)2005 public void setPasspointManagementObjectTree(String passpointManagementObjectTree) { 2006 mPasspointManagementObjectTree = passpointManagementObjectTree; 2007 } 2008 2009 /** @hide */ getMoTree()2010 public String getMoTree() { 2011 return mPasspointManagementObjectTree; 2012 } 2013 2014 /** copy constructor {@hide} */ WifiConfiguration(WifiConfiguration source)2015 public WifiConfiguration(WifiConfiguration source) { 2016 if (source != null) { 2017 networkId = source.networkId; 2018 status = source.status; 2019 SSID = source.SSID; 2020 BSSID = source.BSSID; 2021 FQDN = source.FQDN; 2022 roamingConsortiumIds = source.roamingConsortiumIds.clone(); 2023 providerFriendlyName = source.providerFriendlyName; 2024 isHomeProviderNetwork = source.isHomeProviderNetwork; 2025 preSharedKey = source.preSharedKey; 2026 2027 mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus()); 2028 apBand = source.apBand; 2029 apChannel = source.apChannel; 2030 2031 wepKeys = new String[4]; 2032 for (int i = 0; i < wepKeys.length; i++) { 2033 wepKeys[i] = source.wepKeys[i]; 2034 } 2035 2036 wepTxKeyIndex = source.wepTxKeyIndex; 2037 priority = source.priority; 2038 hiddenSSID = source.hiddenSSID; 2039 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 2040 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 2041 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 2042 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 2043 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 2044 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 2045 2046 defaultGwMacAddress = source.defaultGwMacAddress; 2047 2048 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 2049 2050 if ((source.linkedConfigurations != null) 2051 && (source.linkedConfigurations.size() > 0)) { 2052 linkedConfigurations = new HashMap<String, Integer>(); 2053 linkedConfigurations.putAll(source.linkedConfigurations); 2054 } 2055 mCachedConfigKey = null; //force null configKey 2056 selfAdded = source.selfAdded; 2057 validatedInternetAccess = source.validatedInternetAccess; 2058 isLegacyPasspointConfig = source.isLegacyPasspointConfig; 2059 ephemeral = source.ephemeral; 2060 meteredHint = source.meteredHint; 2061 meteredOverride = source.meteredOverride; 2062 useExternalScores = source.useExternalScores; 2063 2064 didSelfAdd = source.didSelfAdd; 2065 lastConnectUid = source.lastConnectUid; 2066 lastUpdateUid = source.lastUpdateUid; 2067 creatorUid = source.creatorUid; 2068 creatorName = source.creatorName; 2069 lastUpdateName = source.lastUpdateName; 2070 peerWifiConfiguration = source.peerWifiConfiguration; 2071 2072 lastConnected = source.lastConnected; 2073 lastDisconnected = source.lastDisconnected; 2074 numScorerOverride = source.numScorerOverride; 2075 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 2076 numAssociation = source.numAssociation; 2077 userApproved = source.userApproved; 2078 numNoInternetAccessReports = source.numNoInternetAccessReports; 2079 noInternetAccessExpected = source.noInternetAccessExpected; 2080 creationTime = source.creationTime; 2081 updateTime = source.updateTime; 2082 shared = source.shared; 2083 recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus()); 2084 mRandomizedMacAddress = source.mRandomizedMacAddress; 2085 } 2086 } 2087 2088 /** Implement the Parcelable interface {@hide} */ 2089 @Override writeToParcel(Parcel dest, int flags)2090 public void writeToParcel(Parcel dest, int flags) { 2091 dest.writeInt(networkId); 2092 dest.writeInt(status); 2093 mNetworkSelectionStatus.writeToParcel(dest); 2094 dest.writeString(SSID); 2095 dest.writeString(BSSID); 2096 dest.writeInt(apBand); 2097 dest.writeInt(apChannel); 2098 dest.writeString(FQDN); 2099 dest.writeString(providerFriendlyName); 2100 dest.writeInt(isHomeProviderNetwork ? 1 : 0); 2101 dest.writeInt(roamingConsortiumIds.length); 2102 for (long roamingConsortiumId : roamingConsortiumIds) { 2103 dest.writeLong(roamingConsortiumId); 2104 } 2105 dest.writeString(preSharedKey); 2106 for (String wepKey : wepKeys) { 2107 dest.writeString(wepKey); 2108 } 2109 dest.writeInt(wepTxKeyIndex); 2110 dest.writeInt(priority); 2111 dest.writeInt(hiddenSSID ? 1 : 0); 2112 dest.writeInt(requirePMF ? 1 : 0); 2113 dest.writeString(updateIdentifier); 2114 2115 writeBitSet(dest, allowedKeyManagement); 2116 writeBitSet(dest, allowedProtocols); 2117 writeBitSet(dest, allowedAuthAlgorithms); 2118 writeBitSet(dest, allowedPairwiseCiphers); 2119 writeBitSet(dest, allowedGroupCiphers); 2120 2121 dest.writeParcelable(enterpriseConfig, flags); 2122 2123 dest.writeParcelable(mIpConfiguration, flags); 2124 dest.writeString(dhcpServer); 2125 dest.writeString(defaultGwMacAddress); 2126 dest.writeInt(selfAdded ? 1 : 0); 2127 dest.writeInt(didSelfAdd ? 1 : 0); 2128 dest.writeInt(validatedInternetAccess ? 1 : 0); 2129 dest.writeInt(isLegacyPasspointConfig ? 1 : 0); 2130 dest.writeInt(ephemeral ? 1 : 0); 2131 dest.writeInt(meteredHint ? 1 : 0); 2132 dest.writeInt(meteredOverride); 2133 dest.writeInt(useExternalScores ? 1 : 0); 2134 dest.writeInt(creatorUid); 2135 dest.writeInt(lastConnectUid); 2136 dest.writeInt(lastUpdateUid); 2137 dest.writeString(creatorName); 2138 dest.writeString(lastUpdateName); 2139 dest.writeInt(numScorerOverride); 2140 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 2141 dest.writeInt(numAssociation); 2142 dest.writeInt(userApproved); 2143 dest.writeInt(numNoInternetAccessReports); 2144 dest.writeInt(noInternetAccessExpected ? 1 : 0); 2145 dest.writeInt(shared ? 1 : 0); 2146 dest.writeString(mPasspointManagementObjectTree); 2147 dest.writeInt(recentFailure.getAssociationStatus()); 2148 dest.writeParcelable(mRandomizedMacAddress, flags); 2149 } 2150 2151 /** Implement the Parcelable interface {@hide} */ 2152 public static final Creator<WifiConfiguration> CREATOR = 2153 new Creator<WifiConfiguration>() { 2154 public WifiConfiguration createFromParcel(Parcel in) { 2155 WifiConfiguration config = new WifiConfiguration(); 2156 config.networkId = in.readInt(); 2157 config.status = in.readInt(); 2158 config.mNetworkSelectionStatus.readFromParcel(in); 2159 config.SSID = in.readString(); 2160 config.BSSID = in.readString(); 2161 config.apBand = in.readInt(); 2162 config.apChannel = in.readInt(); 2163 config.FQDN = in.readString(); 2164 config.providerFriendlyName = in.readString(); 2165 config.isHomeProviderNetwork = in.readInt() != 0; 2166 int numRoamingConsortiumIds = in.readInt(); 2167 config.roamingConsortiumIds = new long[numRoamingConsortiumIds]; 2168 for (int i = 0; i < numRoamingConsortiumIds; i++) { 2169 config.roamingConsortiumIds[i] = in.readLong(); 2170 } 2171 config.preSharedKey = in.readString(); 2172 for (int i = 0; i < config.wepKeys.length; i++) { 2173 config.wepKeys[i] = in.readString(); 2174 } 2175 config.wepTxKeyIndex = in.readInt(); 2176 config.priority = in.readInt(); 2177 config.hiddenSSID = in.readInt() != 0; 2178 config.requirePMF = in.readInt() != 0; 2179 config.updateIdentifier = in.readString(); 2180 2181 config.allowedKeyManagement = readBitSet(in); 2182 config.allowedProtocols = readBitSet(in); 2183 config.allowedAuthAlgorithms = readBitSet(in); 2184 config.allowedPairwiseCiphers = readBitSet(in); 2185 config.allowedGroupCiphers = readBitSet(in); 2186 2187 config.enterpriseConfig = in.readParcelable(null); 2188 config.setIpConfiguration(in.readParcelable(null)); 2189 config.dhcpServer = in.readString(); 2190 config.defaultGwMacAddress = in.readString(); 2191 config.selfAdded = in.readInt() != 0; 2192 config.didSelfAdd = in.readInt() != 0; 2193 config.validatedInternetAccess = in.readInt() != 0; 2194 config.isLegacyPasspointConfig = in.readInt() != 0; 2195 config.ephemeral = in.readInt() != 0; 2196 config.meteredHint = in.readInt() != 0; 2197 config.meteredOverride = in.readInt(); 2198 config.useExternalScores = in.readInt() != 0; 2199 config.creatorUid = in.readInt(); 2200 config.lastConnectUid = in.readInt(); 2201 config.lastUpdateUid = in.readInt(); 2202 config.creatorName = in.readString(); 2203 config.lastUpdateName = in.readString(); 2204 config.numScorerOverride = in.readInt(); 2205 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 2206 config.numAssociation = in.readInt(); 2207 config.userApproved = in.readInt(); 2208 config.numNoInternetAccessReports = in.readInt(); 2209 config.noInternetAccessExpected = in.readInt() != 0; 2210 config.shared = in.readInt() != 0; 2211 config.mPasspointManagementObjectTree = in.readString(); 2212 config.recentFailure.setAssociationStatus(in.readInt()); 2213 config.mRandomizedMacAddress = in.readParcelable(null); 2214 return config; 2215 } 2216 2217 public WifiConfiguration[] newArray(int size) { 2218 return new WifiConfiguration[size]; 2219 } 2220 }; 2221 2222 /** 2223 * Serializes the object for backup 2224 * @hide 2225 */ getBytesForBackup()2226 public byte[] getBytesForBackup() throws IOException { 2227 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2228 DataOutputStream out = new DataOutputStream(baos); 2229 2230 out.writeInt(BACKUP_VERSION); 2231 BackupUtils.writeString(out, SSID); 2232 out.writeInt(apBand); 2233 out.writeInt(apChannel); 2234 BackupUtils.writeString(out, preSharedKey); 2235 out.writeInt(getAuthType()); 2236 return baos.toByteArray(); 2237 } 2238 2239 /** 2240 * Deserializes a byte array into the WiFiConfiguration Object 2241 * @hide 2242 */ getWifiConfigFromBackup(DataInputStream in)2243 public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException, 2244 BackupUtils.BadVersionException { 2245 WifiConfiguration config = new WifiConfiguration(); 2246 int version = in.readInt(); 2247 if (version < 1 || version > BACKUP_VERSION) { 2248 throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); 2249 } 2250 2251 if (version == 1) return null; // Version 1 is a bad dataset. 2252 2253 config.SSID = BackupUtils.readString(in); 2254 config.apBand = in.readInt(); 2255 config.apChannel = in.readInt(); 2256 config.preSharedKey = BackupUtils.readString(in); 2257 config.allowedKeyManagement.set(in.readInt()); 2258 return config; 2259 } 2260 } 2261