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