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