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