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 * @deprecated it is not used any more. 821 * This network is disabled because higher layer (>2) network is bad 822 */ 823 public static final int DISABLED_BAD_LINK = 1; 824 /** 825 * This network is disabled because multiple association rejects 826 */ 827 public static final int DISABLED_ASSOCIATION_REJECTION = 2; 828 /** 829 * This network is disabled because multiple authentication failure 830 */ 831 public static final int DISABLED_AUTHENTICATION_FAILURE = 3; 832 /** 833 * This network is disabled because multiple DHCP failure 834 */ 835 public static final int DISABLED_DHCP_FAILURE = 4; 836 /** 837 * This network is disabled because of security network but no credentials 838 */ 839 public static final int DISABLED_DNS_FAILURE = 5; 840 /** 841 * This network is disabled because EAP-TLS failure 842 */ 843 public static final int DISABLED_TLS_VERSION_MISMATCH = 6; 844 /** 845 * This network is disabled due to WifiManager disable it explicitly 846 */ 847 public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 7; 848 /** 849 * This network is disabled because no Internet connected and user do not want 850 */ 851 public static final int DISABLED_NO_INTERNET = 8; 852 /** 853 * This network is disabled due to WifiManager disable it explicitly 854 */ 855 public static final int DISABLED_BY_WIFI_MANAGER = 9; 856 /** 857 * This Maximum disable reason value 858 */ 859 public static final int NETWORK_SELECTION_DISABLED_MAX = 10; 860 861 /** 862 * Quality network selection disable reason String (for debug purpose) 863 */ 864 private static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = { 865 "NETWORK_SELECTION_ENABLE", 866 "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated 867 "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ", 868 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE", 869 "NETWORK_SELECTION_DISABLED_DHCP_FAILURE", 870 "NETWORK_SELECTION_DISABLED_DNS_FAILURE", 871 "NETWORK_SELECTION_DISABLED_TLS_VERSION", 872 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS", 873 "NETWORK_SELECTION_DISABLED_NO_INTERNET", 874 "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER"}; 875 876 /** 877 * Invalid time stamp for network selection disable 878 */ 879 public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L; 880 881 /** 882 * This constant indicates the current configuration has connect choice set 883 */ 884 private static final int CONNECT_CHOICE_EXISTS = 1; 885 886 /** 887 * This constant indicates the current configuration does not have connect choice set 888 */ 889 private static final int CONNECT_CHOICE_NOT_EXISTS = -1; 890 891 // fields for QualityNetwork Selection 892 /** 893 * Network selection status, should be in one of three status: enable, temporaily disabled 894 * or permanently disabled 895 */ 896 private int mStatus; 897 898 /** 899 * Reason for disable this network 900 */ 901 private int mNetworkSelectionDisableReason; 902 903 /** 904 * Last time we temporarily disabled the configuration 905 */ 906 private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 907 908 /** 909 * counter for each Network selection disable reason 910 */ 911 private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX]; 912 913 /** 914 * Connect Choice over this configuration 915 * 916 * When current wifi configuration is visible to the user but user explicitly choose to 917 * connect to another network X, the another networks X's configure key will be stored here. 918 * We will consider user has a preference of X over this network. And in the future, 919 * network selection will always give X a higher preference over this configuration. 920 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 921 */ 922 private String mConnectChoice; 923 924 /** 925 * The system timestamp when we records the connectChoice. This value is obtained from 926 * System.currentTimeMillis 927 */ 928 private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 929 930 /** 931 * Used to cache the temporary candidate during the network selection procedure. It will be 932 * kept updating once a new scan result has a higher score than current one 933 */ 934 private ScanResult mCandidate; 935 936 /** 937 * Used to cache the score of the current temporary candidate during the network 938 * selection procedure. 939 */ 940 private int mCandidateScore; 941 942 /** 943 * Indicate whether this network is visible in latest Qualified Network Selection. This 944 * means there is scan result found related to this Configuration and meet the minimum 945 * requirement. The saved network need not join latest Qualified Network Selection. For 946 * example, it is disabled. True means network is visible in latest Qualified Network 947 * Selection and false means network is invisible 948 */ 949 private boolean mSeenInLastQualifiedNetworkSelection; 950 951 /** 952 * Boolean indicating if we have ever successfully connected to this network. 953 * 954 * This value will be set to true upon a successful connection. 955 * This value will be set to false if a previous value was not stored in the config or if 956 * the credentials are updated (ex. a password change). 957 */ 958 private boolean mHasEverConnected; 959 960 /** 961 * set whether this network is visible in latest Qualified Network Selection 962 * @param seen value set to candidate 963 */ 964 public void setSeenInLastQualifiedNetworkSelection(boolean seen) { 965 mSeenInLastQualifiedNetworkSelection = seen; 966 } 967 968 /** 969 * get whether this network is visible in latest Qualified Network Selection 970 * @return returns true -- network is visible in latest Qualified Network Selection 971 * false -- network is invisible in latest Qualified Network Selection 972 */ 973 public boolean getSeenInLastQualifiedNetworkSelection() { 974 return mSeenInLastQualifiedNetworkSelection; 975 } 976 /** 977 * set the temporary candidate of current network selection procedure 978 * @param scanCandidate {@link ScanResult} the candidate set to mCandidate 979 */ 980 public void setCandidate(ScanResult scanCandidate) { 981 mCandidate = scanCandidate; 982 } 983 984 /** 985 * get the temporary candidate of current network selection procedure 986 * @return returns {@link ScanResult} temporary candidate of current network selection 987 * procedure 988 */ 989 public ScanResult getCandidate() { 990 return mCandidate; 991 } 992 993 /** 994 * set the score of the temporary candidate of current network selection procedure 995 * @param score value set to mCandidateScore 996 */ 997 public void setCandidateScore(int score) { 998 mCandidateScore = score; 999 } 1000 1001 /** 1002 * get the score of the temporary candidate of current network selection procedure 1003 * @return returns score of the temporary candidate of current network selection procedure 1004 */ 1005 public int getCandidateScore() { 1006 return mCandidateScore; 1007 } 1008 1009 /** 1010 * get user preferred choice over this configuration 1011 *@return returns configKey of user preferred choice over this configuration 1012 */ 1013 public String getConnectChoice() { 1014 return mConnectChoice; 1015 } 1016 1017 /** 1018 * set user preferred choice over this configuration 1019 * @param newConnectChoice, the configKey of user preferred choice over this configuration 1020 */ 1021 public void setConnectChoice(String newConnectChoice) { 1022 mConnectChoice = newConnectChoice; 1023 } 1024 1025 /** 1026 * get the timeStamp when user select a choice over this configuration 1027 * @return returns when current connectChoice is set (time from System.currentTimeMillis) 1028 */ 1029 public long getConnectChoiceTimestamp() { 1030 return mConnectChoiceTimestamp; 1031 } 1032 1033 /** 1034 * set the timeStamp when user select a choice over this configuration 1035 * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should 1036 * be obtained from System.currentTimeMillis 1037 */ 1038 public void setConnectChoiceTimestamp(long timeStamp) { 1039 mConnectChoiceTimestamp = timeStamp; 1040 } 1041 1042 /** 1043 * get current Quality network selection status 1044 * @return returns current Quality network selection status in String (for debug purpose) 1045 */ 1046 public String getNetworkStatusString() { 1047 return QUALITY_NETWORK_SELECTION_STATUS[mStatus]; 1048 } 1049 1050 public void setHasEverConnected(boolean value) { 1051 mHasEverConnected = value; 1052 } 1053 1054 public boolean getHasEverConnected() { 1055 return mHasEverConnected; 1056 } 1057 1058 private NetworkSelectionStatus() { 1059 // previously stored configs will not have this parameter, so we default to false. 1060 mHasEverConnected = false; 1061 }; 1062 1063 /** 1064 * @param reason specific error reason 1065 * @return corresponding network disable reason String (for debug purpose) 1066 */ 1067 public static String getNetworkDisableReasonString(int reason) { 1068 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1069 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[reason]; 1070 } else { 1071 return null; 1072 } 1073 } 1074 /** 1075 * get current network disable reason 1076 * @return current network disable reason in String (for debug purpose) 1077 */ 1078 public String getNetworkDisableReasonString() { 1079 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[mNetworkSelectionDisableReason]; 1080 } 1081 1082 /** 1083 * get current network network selection status 1084 * @return return current network network selection status 1085 */ 1086 public int getNetworkSelectionStatus() { 1087 return mStatus; 1088 } 1089 /** 1090 * @return whether current network is enabled to join network selection 1091 */ 1092 public boolean isNetworkEnabled() { 1093 return mStatus == NETWORK_SELECTION_ENABLED; 1094 } 1095 1096 /** 1097 * @return whether current network is temporary disabled 1098 */ 1099 public boolean isNetworkTemporaryDisabled() { 1100 return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED; 1101 } 1102 1103 /** 1104 * @return returns whether current network is permanently disabled 1105 */ 1106 public boolean isNetworkPermanentlyDisabled() { 1107 return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED; 1108 } 1109 1110 /** 1111 * set current networ work selection status 1112 * @param status network selection status to set 1113 */ 1114 public void setNetworkSelectionStatus(int status) { 1115 if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) { 1116 mStatus = status; 1117 } 1118 } 1119 1120 /** 1121 * @return returns current network's disable reason 1122 */ 1123 public int getNetworkSelectionDisableReason() { 1124 return mNetworkSelectionDisableReason; 1125 } 1126 1127 /** 1128 * set Network disable reason 1129 * @param reason Network disable reason 1130 */ 1131 public void setNetworkSelectionDisableReason(int reason) { 1132 if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) { 1133 mNetworkSelectionDisableReason = reason; 1134 } else { 1135 throw new IllegalArgumentException("Illegal reason value: " + reason); 1136 } 1137 } 1138 1139 /** 1140 * check whether network is disabled by this reason 1141 * @param reason a specific disable reason 1142 * @return true -- network is disabled for this reason 1143 * false -- network is not disabled for this reason 1144 */ 1145 public boolean isDisabledByReason(int reason) { 1146 return mNetworkSelectionDisableReason == reason; 1147 } 1148 1149 /** 1150 * @param timeStamp Set when current network is disabled in millisecond since January 1, 1151 * 1970 00:00:00.0 UTC 1152 */ 1153 public void setDisableTime(long timeStamp) { 1154 mTemporarilyDisabledTimestamp = timeStamp; 1155 } 1156 1157 /** 1158 * @return returns when current network is disabled in millisecond since January 1, 1159 * 1970 00:00:00.0 UTC 1160 */ 1161 public long getDisableTime() { 1162 return mTemporarilyDisabledTimestamp; 1163 } 1164 1165 /** 1166 * get the disable counter of a specific reason 1167 * @param reason specific failure reason 1168 * @exception throw IllegalArgumentException for illegal input 1169 * @return counter number for specific error reason. 1170 */ 1171 public int getDisableReasonCounter(int reason) { 1172 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1173 return mNetworkSeclectionDisableCounter[reason]; 1174 } else { 1175 throw new IllegalArgumentException("Illegal reason value: " + reason); 1176 } 1177 } 1178 1179 /** 1180 * set the counter of a specific failure reason 1181 * @param reason reason for disable error 1182 * @param value the counter value for this specific reason 1183 * @exception throw IllegalArgumentException for illegal input 1184 */ 1185 public void setDisableReasonCounter(int reason, int value) { 1186 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1187 mNetworkSeclectionDisableCounter[reason] = value; 1188 } else { 1189 throw new IllegalArgumentException("Illegal reason value: " + reason); 1190 } 1191 } 1192 1193 /** 1194 * increment the counter of a specific failure reason 1195 * @param reason a specific failure reason 1196 * @exception throw IllegalArgumentException for illegal input 1197 */ 1198 public void incrementDisableReasonCounter(int reason) { 1199 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1200 mNetworkSeclectionDisableCounter[reason]++; 1201 } else { 1202 throw new IllegalArgumentException("Illegal reason value: " + reason); 1203 } 1204 } 1205 1206 /** 1207 * clear the counter of a specific failure reason 1208 * @hide 1209 * @param reason a specific failure reason 1210 * @exception throw IllegalArgumentException for illegal input 1211 */ 1212 public void clearDisableReasonCounter(int reason) { 1213 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1214 mNetworkSeclectionDisableCounter[reason] = NETWORK_SELECTION_ENABLE; 1215 } else { 1216 throw new IllegalArgumentException("Illegal reason value: " + reason); 1217 } 1218 } 1219 1220 /** 1221 * clear all the failure reason counters 1222 */ 1223 public void clearDisableReasonCounter() { 1224 Arrays.fill(mNetworkSeclectionDisableCounter, NETWORK_SELECTION_ENABLE); 1225 } 1226 1227 /** 1228 * BSSID for connection to this network (through network selection procedure) 1229 */ 1230 private String mNetworkSelectionBSSID; 1231 1232 /** 1233 * get current network Selection BSSID 1234 * @return current network Selection BSSID 1235 */ 1236 public String getNetworkSelectionBSSID() { 1237 return mNetworkSelectionBSSID; 1238 } 1239 1240 /** 1241 * set network Selection BSSID 1242 * @param bssid The target BSSID for assocaition 1243 */ 1244 public void setNetworkSelectionBSSID(String bssid) { 1245 mNetworkSelectionBSSID = bssid; 1246 } 1247 1248 public void copy(NetworkSelectionStatus source) { 1249 mStatus = source.mStatus; 1250 mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason; 1251 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1252 index++) { 1253 mNetworkSeclectionDisableCounter[index] = 1254 source.mNetworkSeclectionDisableCounter[index]; 1255 } 1256 mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp; 1257 mNetworkSelectionBSSID = source.mNetworkSelectionBSSID; 1258 setConnectChoice(source.getConnectChoice()); 1259 setConnectChoiceTimestamp(source.getConnectChoiceTimestamp()); 1260 setHasEverConnected(source.getHasEverConnected()); 1261 } 1262 1263 public void writeToParcel(Parcel dest) { 1264 dest.writeInt(getNetworkSelectionStatus()); 1265 dest.writeInt(getNetworkSelectionDisableReason()); 1266 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1267 index++) { 1268 dest.writeInt(getDisableReasonCounter(index)); 1269 } 1270 dest.writeLong(getDisableTime()); 1271 dest.writeString(getNetworkSelectionBSSID()); 1272 if (getConnectChoice() != null) { 1273 dest.writeInt(CONNECT_CHOICE_EXISTS); 1274 dest.writeString(getConnectChoice()); 1275 dest.writeLong(getConnectChoiceTimestamp()); 1276 } else { 1277 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); 1278 } 1279 dest.writeInt(getHasEverConnected() ? 1 : 0); 1280 } 1281 1282 public void readFromParcel(Parcel in) { 1283 setNetworkSelectionStatus(in.readInt()); 1284 setNetworkSelectionDisableReason(in.readInt()); 1285 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1286 index++) { 1287 setDisableReasonCounter(index, in.readInt()); 1288 } 1289 setDisableTime(in.readLong()); 1290 setNetworkSelectionBSSID(in.readString()); 1291 if (in.readInt() == CONNECT_CHOICE_EXISTS) { 1292 setConnectChoice(in.readString()); 1293 setConnectChoiceTimestamp(in.readLong()); 1294 } else { 1295 setConnectChoice(null); 1296 setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); 1297 } 1298 setHasEverConnected(in.readInt() != 0); 1299 } 1300 } 1301 1302 /** 1303 * @hide 1304 * network selection related member 1305 */ 1306 private final NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus(); 1307 1308 /** 1309 * @hide 1310 * @return network selection status 1311 */ 1312 public NetworkSelectionStatus getNetworkSelectionStatus() { 1313 return mNetworkSelectionStatus; 1314 } 1315 /** 1316 * @hide 1317 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 1318 * regarding roaming and auto-joining. 1319 * The linked configuration may or may not have same SSID, and may or may not have same 1320 * credentials. 1321 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 1322 */ 1323 public HashMap<String, Integer> linkedConfigurations; 1324 1325 public WifiConfiguration() { 1326 networkId = INVALID_NETWORK_ID; 1327 SSID = null; 1328 BSSID = null; 1329 FQDN = null; 1330 roamingConsortiumIds = new long[0]; 1331 priority = 0; 1332 hiddenSSID = false; 1333 allowedKeyManagement = new BitSet(); 1334 allowedProtocols = new BitSet(); 1335 allowedAuthAlgorithms = new BitSet(); 1336 allowedPairwiseCiphers = new BitSet(); 1337 allowedGroupCiphers = new BitSet(); 1338 wepKeys = new String[4]; 1339 for (int i = 0; i < wepKeys.length; i++) { 1340 wepKeys[i] = null; 1341 } 1342 enterpriseConfig = new WifiEnterpriseConfig(); 1343 selfAdded = false; 1344 didSelfAdd = false; 1345 ephemeral = false; 1346 meteredHint = false; 1347 useExternalScores = false; 1348 validatedInternetAccess = false; 1349 mIpConfiguration = new IpConfiguration(); 1350 lastUpdateUid = -1; 1351 creatorUid = -1; 1352 shared = true; 1353 dtimInterval = 0; 1354 } 1355 1356 /** 1357 * Identify if this configuration represents a passpoint network 1358 */ 1359 public boolean isPasspoint() { 1360 return !TextUtils.isEmpty(FQDN) 1361 && !TextUtils.isEmpty(providerFriendlyName) 1362 && enterpriseConfig != null 1363 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 1364 } 1365 1366 /** 1367 * Helper function, identify if a configuration is linked 1368 * @hide 1369 */ 1370 public boolean isLinked(WifiConfiguration config) { 1371 if (config != null) { 1372 if (config.linkedConfigurations != null && linkedConfigurations != null) { 1373 if (config.linkedConfigurations.get(configKey()) != null 1374 && linkedConfigurations.get(config.configKey()) != null) { 1375 return true; 1376 } 1377 } 1378 } 1379 return false; 1380 } 1381 1382 /** 1383 * Helper function, idenfity if a configuration should be treated as an enterprise network 1384 * @hide 1385 */ 1386 public boolean isEnterprise() { 1387 return allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1388 allowedKeyManagement.get(KeyMgmt.IEEE8021X); 1389 } 1390 1391 @Override 1392 public String toString() { 1393 StringBuilder sbuf = new StringBuilder(); 1394 if (this.status == WifiConfiguration.Status.CURRENT) { 1395 sbuf.append("* "); 1396 } else if (this.status == WifiConfiguration.Status.DISABLED) { 1397 sbuf.append("- DSBLE "); 1398 } 1399 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 1400 append(" PROVIDER-NAME: ").append(this.providerFriendlyName). 1401 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN) 1402 .append(" PRIO: ").append(this.priority) 1403 .append(" HIDDEN: ").append(this.hiddenSSID) 1404 .append('\n'); 1405 1406 1407 sbuf.append(" NetworkSelectionStatus ") 1408 .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n"); 1409 if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) { 1410 sbuf.append(" mNetworkSelectionDisableReason ") 1411 .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n"); 1412 1413 for (int index = mNetworkSelectionStatus.NETWORK_SELECTION_ENABLE; 1414 index < mNetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) { 1415 if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) { 1416 sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index) 1417 + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index) 1418 + "\n"); 1419 } 1420 } 1421 } 1422 if (mNetworkSelectionStatus.getConnectChoice() != null) { 1423 sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); 1424 sbuf.append(" connect choice set time: ").append(mNetworkSelectionStatus 1425 .getConnectChoiceTimestamp()); 1426 } 1427 sbuf.append(" hasEverConnected: ") 1428 .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n"); 1429 1430 if (this.numAssociation > 0) { 1431 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 1432 } 1433 if (this.numNoInternetAccessReports > 0) { 1434 sbuf.append(" numNoInternetAccessReports "); 1435 sbuf.append(this.numNoInternetAccessReports).append("\n"); 1436 } 1437 if (this.updateTime != null) { 1438 sbuf.append("update ").append(this.updateTime).append("\n"); 1439 } 1440 if (this.creationTime != null) { 1441 sbuf.append("creation").append(this.creationTime).append("\n"); 1442 } 1443 if (this.didSelfAdd) sbuf.append(" didSelfAdd"); 1444 if (this.selfAdded) sbuf.append(" selfAdded"); 1445 if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); 1446 if (this.ephemeral) sbuf.append(" ephemeral"); 1447 if (this.meteredHint) sbuf.append(" meteredHint"); 1448 if (this.useExternalScores) sbuf.append(" useExternalScores"); 1449 if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess 1450 || this.ephemeral || this.meteredHint || this.useExternalScores) { 1451 sbuf.append("\n"); 1452 } 1453 sbuf.append(" KeyMgmt:"); 1454 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 1455 if (this.allowedKeyManagement.get(k)) { 1456 sbuf.append(" "); 1457 if (k < KeyMgmt.strings.length) { 1458 sbuf.append(KeyMgmt.strings[k]); 1459 } else { 1460 sbuf.append("??"); 1461 } 1462 } 1463 } 1464 sbuf.append(" Protocols:"); 1465 for (int p = 0; p < this.allowedProtocols.size(); p++) { 1466 if (this.allowedProtocols.get(p)) { 1467 sbuf.append(" "); 1468 if (p < Protocol.strings.length) { 1469 sbuf.append(Protocol.strings[p]); 1470 } else { 1471 sbuf.append("??"); 1472 } 1473 } 1474 } 1475 sbuf.append('\n'); 1476 sbuf.append(" AuthAlgorithms:"); 1477 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 1478 if (this.allowedAuthAlgorithms.get(a)) { 1479 sbuf.append(" "); 1480 if (a < AuthAlgorithm.strings.length) { 1481 sbuf.append(AuthAlgorithm.strings[a]); 1482 } else { 1483 sbuf.append("??"); 1484 } 1485 } 1486 } 1487 sbuf.append('\n'); 1488 sbuf.append(" PairwiseCiphers:"); 1489 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 1490 if (this.allowedPairwiseCiphers.get(pc)) { 1491 sbuf.append(" "); 1492 if (pc < PairwiseCipher.strings.length) { 1493 sbuf.append(PairwiseCipher.strings[pc]); 1494 } else { 1495 sbuf.append("??"); 1496 } 1497 } 1498 } 1499 sbuf.append('\n'); 1500 sbuf.append(" GroupCiphers:"); 1501 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 1502 if (this.allowedGroupCiphers.get(gc)) { 1503 sbuf.append(" "); 1504 if (gc < GroupCipher.strings.length) { 1505 sbuf.append(GroupCipher.strings[gc]); 1506 } else { 1507 sbuf.append("??"); 1508 } 1509 } 1510 } 1511 sbuf.append('\n').append(" PSK: "); 1512 if (this.preSharedKey != null) { 1513 sbuf.append('*'); 1514 } 1515 sbuf.append("\nEnterprise config:\n"); 1516 sbuf.append(enterpriseConfig); 1517 1518 sbuf.append("IP config:\n"); 1519 sbuf.append(mIpConfiguration.toString()); 1520 1521 if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) { 1522 sbuf.append(" networkSelectionBSSID=" 1523 + mNetworkSelectionStatus.getNetworkSelectionBSSID()); 1524 } 1525 long now_ms = System.currentTimeMillis(); 1526 if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus 1527 .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) { 1528 sbuf.append('\n'); 1529 long diff = now_ms - mNetworkSelectionStatus.getDisableTime(); 1530 if (diff <= 0) { 1531 sbuf.append(" blackListed since <incorrect>"); 1532 } else { 1533 sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec "); 1534 } 1535 } 1536 if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid); 1537 if (creatorName != null) sbuf.append(" cname=" + creatorName); 1538 if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid); 1539 if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName); 1540 sbuf.append(" lcuid=" + lastConnectUid); 1541 sbuf.append(" userApproved=" + userApprovedAsString(userApproved)); 1542 sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected); 1543 sbuf.append(" "); 1544 1545 if (this.lastConnected != 0) { 1546 sbuf.append('\n'); 1547 long diff = now_ms - this.lastConnected; 1548 if (diff <= 0) { 1549 sbuf.append("lastConnected since <incorrect>"); 1550 } else { 1551 sbuf.append("lastConnected: ").append(Long.toString(diff / 1000)).append("sec "); 1552 } 1553 } 1554 if (this.lastConnectionFailure != 0) { 1555 sbuf.append('\n'); 1556 long diff = now_ms - this.lastConnectionFailure; 1557 if (diff <= 0) { 1558 sbuf.append("lastConnectionFailure since <incorrect> "); 1559 } else { 1560 sbuf.append("lastConnectionFailure: ").append(Long.toString(diff / 1000)); 1561 sbuf.append("sec "); 1562 } 1563 } 1564 if (this.lastRoamingFailure != 0) { 1565 sbuf.append('\n'); 1566 long diff = now_ms - this.lastRoamingFailure; 1567 if (diff <= 0) { 1568 sbuf.append("lastRoamingFailure since <incorrect> "); 1569 } else { 1570 sbuf.append("lastRoamingFailure: ").append(Long.toString(diff / 1000)); 1571 sbuf.append("sec "); 1572 } 1573 } 1574 sbuf.append("roamingFailureBlackListTimeMilli: "). 1575 append(Long.toString(this.roamingFailureBlackListTimeMilli)); 1576 sbuf.append('\n'); 1577 if (this.linkedConfigurations != null) { 1578 for (String key : this.linkedConfigurations.keySet()) { 1579 sbuf.append(" linked: ").append(key); 1580 sbuf.append('\n'); 1581 } 1582 } 1583 sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI); 1584 sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI); 1585 sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI); 1586 sbuf.append('\n'); 1587 sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI); 1588 sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI); 1589 sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI); 1590 sbuf.append('\n'); 1591 sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts); 1592 sbuf.append('\n'); 1593 1594 return sbuf.toString(); 1595 } 1596 1597 /** {@hide} */ 1598 public String getPrintableSsid() { 1599 if (SSID == null) return ""; 1600 final int length = SSID.length(); 1601 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 1602 return SSID.substring(1, length - 1); 1603 } 1604 1605 /** The ascii-encoded string format is P"<ascii-encoded-string>" 1606 * The decoding is implemented in the supplicant for a newly configured 1607 * network. 1608 */ 1609 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 1610 (SSID.charAt(length-1) == '"')) { 1611 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 1612 SSID.substring(2, length - 1)); 1613 return wifiSsid.toString(); 1614 } 1615 return SSID; 1616 } 1617 1618 /** @hide **/ 1619 public static String userApprovedAsString(int userApproved) { 1620 switch (userApproved) { 1621 case USER_APPROVED: 1622 return "USER_APPROVED"; 1623 case USER_BANNED: 1624 return "USER_BANNED"; 1625 case USER_UNSPECIFIED: 1626 return "USER_UNSPECIFIED"; 1627 default: 1628 return "INVALID"; 1629 } 1630 } 1631 1632 /** 1633 * Get an identifier for associating credentials with this config 1634 * @param current configuration contains values for additional fields 1635 * that are not part of this configuration. Used 1636 * when a config with some fields is passed by an application. 1637 * @throws IllegalStateException if config is invalid for key id generation 1638 * @hide 1639 */ 1640 public String getKeyIdForCredentials(WifiConfiguration current) { 1641 String keyMgmt = null; 1642 1643 try { 1644 // Get current config details for fields that are not initialized 1645 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 1646 if (allowedKeyManagement.cardinality() == 0) { 1647 allowedKeyManagement = current.allowedKeyManagement; 1648 } 1649 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1650 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1651 } 1652 if (allowedKeyManagement.get(KeyMgmt.OSEN)) { 1653 keyMgmt = KeyMgmt.strings[KeyMgmt.OSEN]; 1654 } 1655 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1656 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 1657 } 1658 1659 if (TextUtils.isEmpty(keyMgmt)) { 1660 throw new IllegalStateException("Not an EAP network"); 1661 } 1662 1663 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 1664 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 1665 current.enterpriseConfig : null)); 1666 } catch (NullPointerException e) { 1667 throw new IllegalStateException("Invalid config details"); 1668 } 1669 } 1670 1671 private String trimStringForKeyId(String string) { 1672 // Remove quotes and spaces 1673 return string.replace("\"", "").replace(" ", ""); 1674 } 1675 1676 private static BitSet readBitSet(Parcel src) { 1677 int cardinality = src.readInt(); 1678 1679 BitSet set = new BitSet(); 1680 for (int i = 0; i < cardinality; i++) { 1681 set.set(src.readInt()); 1682 } 1683 1684 return set; 1685 } 1686 1687 private static void writeBitSet(Parcel dest, BitSet set) { 1688 int nextSetBit = -1; 1689 1690 dest.writeInt(set.cardinality()); 1691 1692 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1693 dest.writeInt(nextSetBit); 1694 } 1695 } 1696 1697 /** @hide */ 1698 public int getAuthType() { 1699 if (allowedKeyManagement.cardinality() > 1) { 1700 throw new IllegalStateException("More than one auth type set"); 1701 } 1702 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1703 return KeyMgmt.WPA_PSK; 1704 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 1705 return KeyMgmt.WPA2_PSK; 1706 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1707 return KeyMgmt.WPA_EAP; 1708 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1709 return KeyMgmt.IEEE8021X; 1710 } 1711 return KeyMgmt.NONE; 1712 } 1713 1714 /* @hide 1715 * Cache the config key, this seems useful as a speed up since a lot of 1716 * lookups in the config store are done and based on this key. 1717 */ 1718 String mCachedConfigKey; 1719 1720 /** @hide 1721 * return the string used to calculate the hash in WifiConfigStore 1722 * and uniquely identify this WifiConfiguration 1723 */ 1724 public String configKey(boolean allowCached) { 1725 String key; 1726 if (allowCached && mCachedConfigKey != null) { 1727 key = mCachedConfigKey; 1728 } else if (providerFriendlyName != null) { 1729 key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1730 if (!shared) { 1731 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); 1732 } 1733 } else { 1734 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1735 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1736 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1737 allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1738 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1739 } else if (wepKeys[0] != null) { 1740 key = SSID + "WEP"; 1741 } else { 1742 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1743 } 1744 if (!shared) { 1745 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); 1746 } 1747 mCachedConfigKey = key; 1748 } 1749 return key; 1750 } 1751 1752 /** @hide 1753 * get configKey, force calculating the config string 1754 */ 1755 public String configKey() { 1756 return configKey(false); 1757 } 1758 1759 /** @hide */ 1760 public IpConfiguration getIpConfiguration() { 1761 return mIpConfiguration; 1762 } 1763 1764 /** @hide */ 1765 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1766 mIpConfiguration = ipConfiguration; 1767 } 1768 1769 /** @hide */ 1770 public StaticIpConfiguration getStaticIpConfiguration() { 1771 return mIpConfiguration.getStaticIpConfiguration(); 1772 } 1773 1774 /** @hide */ 1775 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 1776 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 1777 } 1778 1779 /** @hide */ 1780 public IpConfiguration.IpAssignment getIpAssignment() { 1781 return mIpConfiguration.ipAssignment; 1782 } 1783 1784 /** @hide */ 1785 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1786 mIpConfiguration.ipAssignment = ipAssignment; 1787 } 1788 1789 /** @hide */ 1790 public IpConfiguration.ProxySettings getProxySettings() { 1791 return mIpConfiguration.proxySettings; 1792 } 1793 1794 /** @hide */ 1795 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1796 mIpConfiguration.proxySettings = proxySettings; 1797 } 1798 1799 /** @hide */ 1800 public ProxyInfo getHttpProxy() { 1801 return mIpConfiguration.httpProxy; 1802 } 1803 1804 /** @hide */ 1805 public void setHttpProxy(ProxyInfo httpProxy) { 1806 mIpConfiguration.httpProxy = httpProxy; 1807 } 1808 1809 /** @hide */ 1810 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1811 mIpConfiguration.proxySettings = settings; 1812 mIpConfiguration.httpProxy = proxy; 1813 } 1814 1815 /** Implement the Parcelable interface {@hide} */ 1816 public int describeContents() { 1817 return 0; 1818 } 1819 1820 /** @hide */ 1821 public void setPasspointManagementObjectTree(String passpointManagementObjectTree) { 1822 mPasspointManagementObjectTree = passpointManagementObjectTree; 1823 } 1824 1825 /** @hide */ 1826 public String getMoTree() { 1827 return mPasspointManagementObjectTree; 1828 } 1829 1830 /** copy constructor {@hide} */ 1831 public WifiConfiguration(WifiConfiguration source) { 1832 if (source != null) { 1833 networkId = source.networkId; 1834 status = source.status; 1835 SSID = source.SSID; 1836 BSSID = source.BSSID; 1837 FQDN = source.FQDN; 1838 roamingConsortiumIds = source.roamingConsortiumIds.clone(); 1839 providerFriendlyName = source.providerFriendlyName; 1840 preSharedKey = source.preSharedKey; 1841 1842 mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus()); 1843 apBand = source.apBand; 1844 apChannel = source.apChannel; 1845 1846 wepKeys = new String[4]; 1847 for (int i = 0; i < wepKeys.length; i++) { 1848 wepKeys[i] = source.wepKeys[i]; 1849 } 1850 1851 wepTxKeyIndex = source.wepTxKeyIndex; 1852 priority = source.priority; 1853 hiddenSSID = source.hiddenSSID; 1854 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 1855 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 1856 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 1857 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 1858 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 1859 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 1860 1861 defaultGwMacAddress = source.defaultGwMacAddress; 1862 1863 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 1864 1865 if ((source.linkedConfigurations != null) 1866 && (source.linkedConfigurations.size() > 0)) { 1867 linkedConfigurations = new HashMap<String, Integer>(); 1868 linkedConfigurations.putAll(source.linkedConfigurations); 1869 } 1870 mCachedConfigKey = null; //force null configKey 1871 selfAdded = source.selfAdded; 1872 validatedInternetAccess = source.validatedInternetAccess; 1873 ephemeral = source.ephemeral; 1874 meteredHint = source.meteredHint; 1875 useExternalScores = source.useExternalScores; 1876 if (source.visibility != null) { 1877 visibility = new Visibility(source.visibility); 1878 } 1879 1880 lastFailure = source.lastFailure; 1881 didSelfAdd = source.didSelfAdd; 1882 lastConnectUid = source.lastConnectUid; 1883 lastUpdateUid = source.lastUpdateUid; 1884 creatorUid = source.creatorUid; 1885 creatorName = source.creatorName; 1886 lastUpdateName = source.lastUpdateName; 1887 peerWifiConfiguration = source.peerWifiConfiguration; 1888 1889 lastConnected = source.lastConnected; 1890 lastDisconnected = source.lastDisconnected; 1891 lastConnectionFailure = source.lastConnectionFailure; 1892 lastRoamingFailure = source.lastRoamingFailure; 1893 lastRoamingFailureReason = source.lastRoamingFailureReason; 1894 roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli; 1895 numScorerOverride = source.numScorerOverride; 1896 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 1897 numAssociation = source.numAssociation; 1898 numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI; 1899 numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI; 1900 numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI; 1901 numTicksAtLowRSSI = source.numTicksAtLowRSSI; 1902 numTicksAtBadRSSI = source.numTicksAtBadRSSI; 1903 numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI; 1904 numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts; 1905 userApproved = source.userApproved; 1906 numNoInternetAccessReports = source.numNoInternetAccessReports; 1907 noInternetAccessExpected = source.noInternetAccessExpected; 1908 creationTime = source.creationTime; 1909 updateTime = source.updateTime; 1910 shared = source.shared; 1911 } 1912 } 1913 1914 /** Implement the Parcelable interface {@hide} */ 1915 @Override 1916 public void writeToParcel(Parcel dest, int flags) { 1917 dest.writeInt(networkId); 1918 dest.writeInt(status); 1919 mNetworkSelectionStatus.writeToParcel(dest); 1920 dest.writeString(SSID); 1921 dest.writeString(BSSID); 1922 dest.writeInt(apBand); 1923 dest.writeInt(apChannel); 1924 dest.writeString(FQDN); 1925 dest.writeString(providerFriendlyName); 1926 dest.writeInt(roamingConsortiumIds.length); 1927 for (long roamingConsortiumId : roamingConsortiumIds) { 1928 dest.writeLong(roamingConsortiumId); 1929 } 1930 dest.writeString(preSharedKey); 1931 for (String wepKey : wepKeys) { 1932 dest.writeString(wepKey); 1933 } 1934 dest.writeInt(wepTxKeyIndex); 1935 dest.writeInt(priority); 1936 dest.writeInt(hiddenSSID ? 1 : 0); 1937 dest.writeInt(requirePMF ? 1 : 0); 1938 dest.writeString(updateIdentifier); 1939 1940 writeBitSet(dest, allowedKeyManagement); 1941 writeBitSet(dest, allowedProtocols); 1942 writeBitSet(dest, allowedAuthAlgorithms); 1943 writeBitSet(dest, allowedPairwiseCiphers); 1944 writeBitSet(dest, allowedGroupCiphers); 1945 1946 dest.writeParcelable(enterpriseConfig, flags); 1947 1948 dest.writeParcelable(mIpConfiguration, flags); 1949 dest.writeString(dhcpServer); 1950 dest.writeString(defaultGwMacAddress); 1951 dest.writeInt(selfAdded ? 1 : 0); 1952 dest.writeInt(didSelfAdd ? 1 : 0); 1953 dest.writeInt(validatedInternetAccess ? 1 : 0); 1954 dest.writeInt(ephemeral ? 1 : 0); 1955 dest.writeInt(meteredHint ? 1 : 0); 1956 dest.writeInt(useExternalScores ? 1 : 0); 1957 dest.writeInt(creatorUid); 1958 dest.writeInt(lastConnectUid); 1959 dest.writeInt(lastUpdateUid); 1960 dest.writeString(creatorName); 1961 dest.writeString(lastUpdateName); 1962 dest.writeLong(lastConnectionFailure); 1963 dest.writeLong(lastRoamingFailure); 1964 dest.writeInt(lastRoamingFailureReason); 1965 dest.writeLong(roamingFailureBlackListTimeMilli); 1966 dest.writeInt(numScorerOverride); 1967 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 1968 dest.writeInt(numAssociation); 1969 dest.writeInt(numUserTriggeredWifiDisableLowRSSI); 1970 dest.writeInt(numUserTriggeredWifiDisableBadRSSI); 1971 dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI); 1972 dest.writeInt(numTicksAtLowRSSI); 1973 dest.writeInt(numTicksAtBadRSSI); 1974 dest.writeInt(numTicksAtNotHighRSSI); 1975 dest.writeInt(numUserTriggeredJoinAttempts); 1976 dest.writeInt(userApproved); 1977 dest.writeInt(numNoInternetAccessReports); 1978 dest.writeInt(noInternetAccessExpected ? 1 : 0); 1979 dest.writeInt(shared ? 1 : 0); 1980 dest.writeString(mPasspointManagementObjectTree); 1981 } 1982 1983 /** Implement the Parcelable interface {@hide} */ 1984 public static final Creator<WifiConfiguration> CREATOR = 1985 new Creator<WifiConfiguration>() { 1986 public WifiConfiguration createFromParcel(Parcel in) { 1987 WifiConfiguration config = new WifiConfiguration(); 1988 config.networkId = in.readInt(); 1989 config.status = in.readInt(); 1990 config.mNetworkSelectionStatus.readFromParcel(in); 1991 config.SSID = in.readString(); 1992 config.BSSID = in.readString(); 1993 config.apBand = in.readInt(); 1994 config.apChannel = in.readInt(); 1995 config.FQDN = in.readString(); 1996 config.providerFriendlyName = in.readString(); 1997 int numRoamingConsortiumIds = in.readInt(); 1998 config.roamingConsortiumIds = new long[numRoamingConsortiumIds]; 1999 for (int i = 0; i < numRoamingConsortiumIds; i++) { 2000 config.roamingConsortiumIds[i] = in.readLong(); 2001 } 2002 config.preSharedKey = in.readString(); 2003 for (int i = 0; i < config.wepKeys.length; i++) { 2004 config.wepKeys[i] = in.readString(); 2005 } 2006 config.wepTxKeyIndex = in.readInt(); 2007 config.priority = in.readInt(); 2008 config.hiddenSSID = in.readInt() != 0; 2009 config.requirePMF = in.readInt() != 0; 2010 config.updateIdentifier = in.readString(); 2011 2012 config.allowedKeyManagement = readBitSet(in); 2013 config.allowedProtocols = readBitSet(in); 2014 config.allowedAuthAlgorithms = readBitSet(in); 2015 config.allowedPairwiseCiphers = readBitSet(in); 2016 config.allowedGroupCiphers = readBitSet(in); 2017 2018 config.enterpriseConfig = in.readParcelable(null); 2019 config.mIpConfiguration = in.readParcelable(null); 2020 config.dhcpServer = in.readString(); 2021 config.defaultGwMacAddress = in.readString(); 2022 config.selfAdded = in.readInt() != 0; 2023 config.didSelfAdd = in.readInt() != 0; 2024 config.validatedInternetAccess = in.readInt() != 0; 2025 config.ephemeral = in.readInt() != 0; 2026 config.meteredHint = in.readInt() != 0; 2027 config.useExternalScores = in.readInt() != 0; 2028 config.creatorUid = in.readInt(); 2029 config.lastConnectUid = in.readInt(); 2030 config.lastUpdateUid = in.readInt(); 2031 config.creatorName = in.readString(); 2032 config.lastUpdateName = in.readString(); 2033 config.lastConnectionFailure = in.readLong(); 2034 config.lastRoamingFailure = in.readLong(); 2035 config.lastRoamingFailureReason = in.readInt(); 2036 config.roamingFailureBlackListTimeMilli = in.readLong(); 2037 config.numScorerOverride = in.readInt(); 2038 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 2039 config.numAssociation = in.readInt(); 2040 config.numUserTriggeredWifiDisableLowRSSI = in.readInt(); 2041 config.numUserTriggeredWifiDisableBadRSSI = in.readInt(); 2042 config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt(); 2043 config.numTicksAtLowRSSI = in.readInt(); 2044 config.numTicksAtBadRSSI = in.readInt(); 2045 config.numTicksAtNotHighRSSI = in.readInt(); 2046 config.numUserTriggeredJoinAttempts = in.readInt(); 2047 config.userApproved = in.readInt(); 2048 config.numNoInternetAccessReports = in.readInt(); 2049 config.noInternetAccessExpected = in.readInt() != 0; 2050 config.shared = in.readInt() != 0; 2051 config.mPasspointManagementObjectTree = in.readString(); 2052 return config; 2053 } 2054 2055 public WifiConfiguration[] newArray(int size) { 2056 return new WifiConfiguration[size]; 2057 } 2058 }; 2059 2060 /** 2061 * Serializes the object for backup 2062 * @hide 2063 */ 2064 public byte[] getBytesForBackup() throws IOException { 2065 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2066 DataOutputStream out = new DataOutputStream(baos); 2067 2068 out.writeInt(BACKUP_VERSION); 2069 BackupUtils.writeString(out, SSID); 2070 out.writeInt(apBand); 2071 out.writeInt(apChannel); 2072 BackupUtils.writeString(out, preSharedKey); 2073 out.writeInt(getAuthType()); 2074 return baos.toByteArray(); 2075 } 2076 2077 /** 2078 * Deserializes a byte array into the WiFiConfiguration Object 2079 * @hide 2080 */ 2081 public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException, 2082 BackupUtils.BadVersionException { 2083 WifiConfiguration config = new WifiConfiguration(); 2084 int version = in.readInt(); 2085 if (version < 1 || version > BACKUP_VERSION) { 2086 throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); 2087 } 2088 2089 if (version == 1) return null; // Version 1 is a bad dataset. 2090 2091 config.SSID = BackupUtils.readString(in); 2092 config.apBand = in.readInt(); 2093 config.apChannel = in.readInt(); 2094 config.preSharedKey = BackupUtils.readString(in); 2095 config.allowedKeyManagement.set(in.readInt()); 2096 return config; 2097 } 2098 } 2099