1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.wifi; 18 19 import android.annotation.SystemApi; 20 import android.net.IpConfiguration; 21 import android.net.IpConfiguration.ProxySettings; 22 import android.net.IpConfiguration.IpAssignment; 23 import android.net.ProxyInfo; 24 import android.net.StaticIpConfiguration; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 import android.text.TextUtils; 28 import android.annotation.SystemApi; 29 30 import java.util.HashMap; 31 import java.util.BitSet; 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.Comparator; 35 36 /** 37 * A class representing a configured Wi-Fi network, including the 38 * security configuration. 39 */ 40 public class WifiConfiguration implements Parcelable { 41 private static final String TAG = "WifiConfiguration"; 42 /** {@hide} */ 43 public static final String ssidVarName = "ssid"; 44 /** {@hide} */ 45 public static final String bssidVarName = "bssid"; 46 /** {@hide} */ 47 public static final String pskVarName = "psk"; 48 /** {@hide} */ 49 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 50 /** {@hide} */ 51 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 52 /** {@hide} */ 53 public static final String priorityVarName = "priority"; 54 /** {@hide} */ 55 public static final String hiddenSSIDVarName = "scan_ssid"; 56 /** {@hide} */ 57 public static final String pmfVarName = "ieee80211w"; 58 /** {@hide} */ 59 public static final String updateIdentiferVarName = "update_identifier"; 60 /** {@hide} */ 61 public static final int INVALID_NETWORK_ID = -1; 62 /** 63 * Recognized key management schemes. 64 */ 65 public static class KeyMgmt { 66 private KeyMgmt() { } 67 68 /** WPA is not used; plaintext or static WEP could be used. */ 69 public static final int NONE = 0; 70 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 71 public static final int WPA_PSK = 1; 72 /** WPA using EAP authentication. Generally used with an external authentication server. */ 73 public static final int WPA_EAP = 2; 74 /** IEEE 802.1X using EAP authentication and (optionally) dynamically 75 * generated WEP keys. */ 76 public static final int IEEE8021X = 3; 77 78 /** WPA2 pre-shared key for use with soft access point 79 * (requires {@code preSharedKey} to be specified). 80 * @hide 81 */ 82 public static final int WPA2_PSK = 4; 83 84 public static final String varName = "key_mgmt"; 85 86 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", 87 "WPA2_PSK" }; 88 } 89 90 /** 91 * Recognized security protocols. 92 */ 93 public static class Protocol { 94 private Protocol() { } 95 96 /** WPA/IEEE 802.11i/D3.0 */ 97 public static final int WPA = 0; 98 /** WPA2/IEEE 802.11i */ 99 public static final int RSN = 1; 100 101 public static final String varName = "proto"; 102 103 public static final String[] strings = { "WPA", "RSN" }; 104 } 105 106 /** 107 * Recognized IEEE 802.11 authentication algorithms. 108 */ 109 public static class AuthAlgorithm { 110 private AuthAlgorithm() { } 111 112 /** Open System authentication (required for WPA/WPA2) */ 113 public static final int OPEN = 0; 114 /** Shared Key authentication (requires static WEP keys) */ 115 public static final int SHARED = 1; 116 /** LEAP/Network EAP (only used with LEAP) */ 117 public static final int LEAP = 2; 118 119 public static final String varName = "auth_alg"; 120 121 public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; 122 } 123 124 /** 125 * Recognized pairwise ciphers for WPA. 126 */ 127 public static class PairwiseCipher { 128 private PairwiseCipher() { } 129 130 /** Use only Group keys (deprecated) */ 131 public static final int NONE = 0; 132 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 133 public static final int TKIP = 1; 134 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 135 public static final int CCMP = 2; 136 137 public static final String varName = "pairwise"; 138 139 public static final String[] strings = { "NONE", "TKIP", "CCMP" }; 140 } 141 142 /** 143 * Recognized group ciphers. 144 * <pre> 145 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 146 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 147 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 148 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 149 * </pre> 150 */ 151 public static class GroupCipher { 152 private GroupCipher() { } 153 154 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */ 155 public static final int WEP40 = 0; 156 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */ 157 public static final int WEP104 = 1; 158 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 159 public static final int TKIP = 2; 160 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 161 public static final int CCMP = 3; 162 163 public static final String varName = "group"; 164 165 public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" }; 166 } 167 168 /** Possible status of a network configuration. */ 169 public static class Status { 170 private Status() { } 171 172 /** this is the network we are currently connected to */ 173 public static final int CURRENT = 0; 174 /** supplicant will not attempt to use this network */ 175 public static final int DISABLED = 1; 176 /** supplicant will consider this network available for association */ 177 public static final int ENABLED = 2; 178 179 public static final String[] strings = { "current", "disabled", "enabled" }; 180 } 181 182 /** @hide */ 183 public static final int DISABLED_UNKNOWN_REASON = 0; 184 /** @hide */ 185 public static final int DISABLED_DNS_FAILURE = 1; 186 /** @hide */ 187 public static final int DISABLED_DHCP_FAILURE = 2; 188 /** @hide */ 189 public static final int DISABLED_AUTH_FAILURE = 3; 190 /** @hide */ 191 public static final int DISABLED_ASSOCIATION_REJECT = 4; 192 /** @hide */ 193 public static final int DISABLED_BY_WIFI_MANAGER = 5; 194 195 /** 196 * The ID number that the supplicant uses to identify this 197 * network configuration entry. This must be passed as an argument 198 * to most calls into the supplicant. 199 */ 200 public int networkId; 201 202 /** 203 * The current status of this network configuration entry. 204 * @see Status 205 */ 206 public int status; 207 208 /** 209 * The configuration needs to be written to networkHistory.txt 210 * @hide 211 */ 212 public boolean dirty; 213 214 /** 215 * The code referring to a reason for disabling the network 216 * Valid when {@link #status} == Status.DISABLED 217 * @hide 218 */ 219 public int disableReason; 220 221 /** 222 * The network's SSID. Can either be an ASCII string, 223 * which must be enclosed in double quotation marks 224 * (e.g., {@code "MyNetwork"}, or a string of 225 * hex digits,which are not enclosed in quotes 226 * (e.g., {@code 01a243f405}). 227 */ 228 public String SSID; 229 /** 230 * When set, this network configuration entry should only be used when 231 * associating with the AP having the specified BSSID. The value is 232 * a string in the format of an Ethernet MAC address, e.g., 233 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 234 */ 235 public String BSSID; 236 /** 237 * Fully qualified domain name (FQDN) of AAA server or RADIUS server 238 * e.g. {@code "mail.example.com"}. 239 */ 240 public String FQDN; 241 /** 242 * Network access identifier (NAI) realm, for Passpoint credential. 243 * e.g. {@code "myhost.example.com"}. 244 * @hide 245 */ 246 public String naiRealm; 247 248 /** 249 * Pre-shared key for use with WPA-PSK. 250 * <p/> 251 * When the value of this key is read, the actual key is 252 * not returned, just a "*" if the key has a value, or the null 253 * string otherwise. 254 */ 255 public String preSharedKey; 256 /** 257 * Up to four WEP keys. Either an ASCII string enclosed in double 258 * quotation marks (e.g., {@code "abcdef"} or a string 259 * of hex digits (e.g., {@code 0102030405}). 260 * <p/> 261 * When the value of one of these keys is read, the actual key is 262 * not returned, just a "*" if the key has a value, or the null 263 * string otherwise. 264 */ 265 public String[] wepKeys; 266 267 /** Default WEP key index, ranging from 0 to 3. */ 268 public int wepTxKeyIndex; 269 270 /** 271 * Priority determines the preference given to a network by {@code wpa_supplicant} 272 * when choosing an access point with which to associate. 273 */ 274 public int priority; 275 276 /** 277 * This is a network that does not broadcast its SSID, so an 278 * SSID-specific probe request must be used for scans. 279 */ 280 public boolean hiddenSSID; 281 282 /** 283 * This is a network that requries Protected Management Frames (PMF). 284 * @hide 285 */ 286 public boolean requirePMF; 287 288 /** 289 * Update identifier, for Passpoint network. 290 * @hide 291 */ 292 public String updateIdentifier; 293 294 /** 295 * The set of key management protocols supported by this configuration. 296 * See {@link KeyMgmt} for descriptions of the values. 297 * Defaults to WPA-PSK WPA-EAP. 298 */ 299 public BitSet allowedKeyManagement; 300 /** 301 * The set of security protocols supported by this configuration. 302 * See {@link Protocol} for descriptions of the values. 303 * Defaults to WPA RSN. 304 */ 305 public BitSet allowedProtocols; 306 /** 307 * The set of authentication protocols supported by this configuration. 308 * See {@link AuthAlgorithm} for descriptions of the values. 309 * Defaults to automatic selection. 310 */ 311 public BitSet allowedAuthAlgorithms; 312 /** 313 * The set of pairwise ciphers for WPA supported by this configuration. 314 * See {@link PairwiseCipher} for descriptions of the values. 315 * Defaults to CCMP TKIP. 316 */ 317 public BitSet allowedPairwiseCiphers; 318 /** 319 * The set of group ciphers supported by this configuration. 320 * See {@link GroupCipher} for descriptions of the values. 321 * Defaults to CCMP TKIP WEP104 WEP40. 322 */ 323 public BitSet allowedGroupCiphers; 324 /** 325 * The enterprise configuration details specifying the EAP method, 326 * certificates and other settings associated with the EAP. 327 */ 328 public WifiEnterpriseConfig enterpriseConfig; 329 330 /** 331 * @hide 332 */ 333 private IpConfiguration mIpConfiguration; 334 335 /** 336 * @hide 337 * dhcp server MAC address if known 338 */ 339 public String dhcpServer; 340 341 /** 342 * @hide 343 * default Gateway MAC address if known 344 */ 345 public String defaultGwMacAddress; 346 347 /** 348 * @hide 349 * last failure 350 */ 351 public String lastFailure; 352 353 /** 354 * @hide 355 * last time we connected, this configuration had no internet access 356 */ 357 public boolean noInternetAccess; 358 359 /** 360 * @hide 361 * Uid of app creating the configuration 362 */ 363 @SystemApi 364 public int creatorUid; 365 366 /** 367 * @hide 368 * Uid of last app issuing a connection related command 369 */ 370 public int lastConnectUid; 371 372 /** 373 * @hide 374 * Uid of last app modifying the configuration 375 */ 376 @SystemApi 377 public int lastUpdateUid; 378 379 /** 380 * @hide 381 * Uid used by autoJoin 382 */ 383 public String autoJoinBSSID; 384 385 /** 386 * @hide 387 * BSSID list on which this configuration was seen. 388 * TODO: prevent this list to grow infinitely, age-out the results 389 */ 390 public HashMap<String, ScanResult> scanResultCache; 391 392 /** The Below RSSI thresholds are used to configure AutoJoin 393 * - GOOD/LOW/BAD thresholds are used so as to calculate link score 394 * - UNWANTED_SOFT are used by the blacklisting logic so as to handle 395 * the unwanted network message coming from CS 396 * - UNBLACKLIST thresholds are used so as to tweak the speed at which 397 * the network is unblacklisted (i.e. if 398 * it is seen with good RSSI, it is blacklisted faster) 399 * - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from 400 * the network we need to be before autojoin kicks in 401 */ 402 /** @hide **/ 403 public static int INVALID_RSSI = -127; 404 405 /** @hide **/ 406 public static int UNWANTED_BLACKLIST_SOFT_RSSI_24 = -80; 407 408 /** @hide **/ 409 public static int UNWANTED_BLACKLIST_SOFT_RSSI_5 = -70; 410 411 /** @hide **/ 412 public static int GOOD_RSSI_24 = -65; 413 414 /** @hide **/ 415 public static int LOW_RSSI_24 = -77; 416 417 /** @hide **/ 418 public static int BAD_RSSI_24 = -87; 419 420 /** @hide **/ 421 public static int GOOD_RSSI_5 = -60; 422 423 /** @hide **/ 424 public static int LOW_RSSI_5 = -72; 425 426 /** @hide **/ 427 public static int BAD_RSSI_5 = -82; 428 429 /** @hide **/ 430 public static int UNWANTED_BLACKLIST_SOFT_BUMP = 4; 431 432 /** @hide **/ 433 public static int UNWANTED_BLACKLIST_HARD_BUMP = 8; 434 435 /** @hide **/ 436 public static int UNBLACKLIST_THRESHOLD_24_SOFT = -77; 437 438 /** @hide **/ 439 public static int UNBLACKLIST_THRESHOLD_24_HARD = -68; 440 441 /** @hide **/ 442 public static int UNBLACKLIST_THRESHOLD_5_SOFT = -63; 443 444 /** @hide **/ 445 public static int UNBLACKLIST_THRESHOLD_5_HARD = -56; 446 447 /** @hide **/ 448 public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_24 = -80; 449 450 /** @hide **/ 451 public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_5 = -70; 452 453 /** @hide 454 * 5GHz band is prefered low over 2.4 if the 5GHz RSSI is higher than this threshold */ 455 public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65; 456 457 /** @hide 458 * 5GHz band is penalized if the 5GHz RSSI is lower than this threshold **/ 459 public static int G_BAND_PREFERENCE_RSSI_THRESHOLD = -75; 460 461 /** @hide 462 * Boost given to RSSI on a home network for the purpose of calculating the score 463 * This adds stickiness to home networks, as defined by: 464 * - less than 4 known BSSIDs 465 * - PSK only 466 * - TODO: add a test to verify that all BSSIDs are behind same gateway 467 ***/ 468 public static int HOME_NETWORK_RSSI_BOOST = 5; 469 470 /** @hide 471 * RSSI boost for configuration which use autoJoinUseAggressiveJoinAttemptThreshold 472 * To be more aggressive when initially attempting to auto join 473 */ 474 public static int MAX_INITIAL_AUTO_JOIN_RSSI_BOOST = 8; 475 476 /** 477 * @hide 478 * A summary of the RSSI and Band status for that configuration 479 * This is used as a temporary value by the auto-join controller 480 */ 481 public final class Visibility { 482 public int rssi5; // strongest 5GHz RSSI 483 public int rssi24; // strongest 2.4GHz RSSI 484 public int num5; // number of BSSIDs on 5GHz 485 public int num24; // number of BSSIDs on 2.4GHz 486 public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen) 487 public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen) 488 public String BSSID24; 489 public String BSSID5; 490 491 public Visibility() { 492 rssi5 = INVALID_RSSI; 493 rssi24 = INVALID_RSSI; 494 } 495 496 public Visibility(Visibility source) { 497 rssi5 = source.rssi5; 498 rssi24 = source.rssi24; 499 age24 = source.age24; 500 age5 = source.age5; 501 num24 = source.num24; 502 num5 = source.num5; 503 BSSID5 = source.BSSID5; 504 BSSID24 = source.BSSID24; 505 } 506 507 @Override 508 public String toString() { 509 StringBuilder sbuf = new StringBuilder(); 510 sbuf.append("["); 511 if (rssi24 > INVALID_RSSI) { 512 sbuf.append(Integer.toString(rssi24)); 513 sbuf.append(","); 514 sbuf.append(Integer.toString(num24)); 515 if (BSSID24 != null) sbuf.append(",").append(BSSID24); 516 } else { 517 sbuf.append("*"); 518 } 519 sbuf.append(" - "); 520 if (rssi5 > INVALID_RSSI) { 521 sbuf.append(Integer.toString(rssi5)); 522 sbuf.append(","); 523 sbuf.append(Integer.toString(num5)); 524 if (BSSID5 != null) sbuf.append(",").append(BSSID5); 525 } 526 sbuf.append("]"); 527 return sbuf.toString(); 528 } 529 } 530 531 /** @hide 532 * Cache the visibility status of this configuration. 533 * Visibility can change at any time depending on scan results availability. 534 * Owner of the WifiConfiguration is responsible to set this field based on 535 * recent scan results. 536 ***/ 537 public Visibility visibility; 538 539 /** @hide 540 * calculate and set Visibility for that configuration. 541 * 542 * age in milliseconds: we will consider only ScanResults that are more recent, 543 * i.e. younger. 544 ***/ 545 public Visibility setVisibility(long age) { 546 if (scanResultCache == null) { 547 visibility = null; 548 return null; 549 } 550 551 Visibility status = new Visibility(); 552 553 long now_ms = System.currentTimeMillis(); 554 for(ScanResult result : scanResultCache.values()) { 555 if (result.seen == 0) 556 continue; 557 558 if (result.is5GHz()) { 559 //strictly speaking: [4915, 5825] 560 //number of known BSSID on 5GHz band 561 status.num5 = status.num5 + 1; 562 } else if (result.is24GHz()) { 563 //strictly speaking: [2412, 2482] 564 //number of known BSSID on 2.4Ghz band 565 status.num24 = status.num24 + 1; 566 } 567 568 if ((now_ms - result.seen) > age) continue; 569 570 if (result.is5GHz()) { 571 if (result.level > status.rssi5) { 572 status.rssi5 = result.level; 573 status.age5 = result.seen; 574 status.BSSID5 = result.BSSID; 575 } 576 } else if (result.is24GHz()) { 577 if (result.level > status.rssi24) { 578 status.rssi24 = result.level; 579 status.age24 = result.seen; 580 status.BSSID24 = result.BSSID; 581 } 582 } 583 } 584 visibility = status; 585 return status; 586 } 587 588 /** @hide */ 589 public static final int AUTO_JOIN_ENABLED = 0; 590 /** 591 * if this is set, the WifiConfiguration cannot use linkages so as to bump 592 * it's relative priority. 593 * - status between and 128 indicate various level of blacklisting depending 594 * on the severity or frequency of the connection error 595 * - deleted status indicates that the user is deleting the configuration, and so 596 * although it may have been self added we will not re-self-add it, ignore it, 597 * not return it to applications, and not connect to it 598 * */ 599 600 /** @hide 601 * network was temporary disabled due to bad connection, most likely due 602 * to weak RSSI */ 603 public static final int AUTO_JOIN_TEMPORARY_DISABLED = 1; 604 /** @hide 605 * network was temporary disabled due to bad connection, which cant be attributed 606 * to weak RSSI */ 607 public static final int AUTO_JOIN_TEMPORARY_DISABLED_LINK_ERRORS = 32; 608 /** @hide */ 609 public static final int AUTO_JOIN_TEMPORARY_DISABLED_AT_SUPPLICANT = 64; 610 /** @hide */ 611 public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE = 128; 612 /** @hide */ 613 public static final int AUTO_JOIN_DISABLED_NO_CREDENTIALS = 160; 614 /** @hide */ 615 public static final int AUTO_JOIN_DISABLED_USER_ACTION = 161; 616 617 /** @hide */ 618 public static final int AUTO_JOIN_DELETED = 200; 619 620 /** 621 * @hide 622 */ 623 public int autoJoinStatus; 624 625 /** 626 * @hide 627 * Number of connection failures 628 */ 629 public int numConnectionFailures; 630 631 /** 632 * @hide 633 * Number of IP config failures 634 */ 635 public int numIpConfigFailures; 636 637 /** 638 * @hide 639 * Number of Auth failures 640 */ 641 public int numAuthFailures; 642 643 /** 644 * @hide 645 * Last time we blacklisted the configuration 646 */ 647 public long blackListTimestamp; 648 649 /** 650 * @hide 651 * Last time the system was connected to this configuration. 652 */ 653 public long lastConnected; 654 655 /** 656 * @hide 657 * Last time the system tried to connect and failed. 658 */ 659 public long lastConnectionFailure; 660 661 /** 662 * @hide 663 * Last time the system was disconnected to this configuration. 664 */ 665 public long lastDisconnected; 666 667 /** 668 * Set if the configuration was self added by the framework 669 * This boolean is cleared if we get a connect/save/ update or 670 * any wifiManager command that indicate the user interacted with the configuration 671 * since we will now consider that the configuration belong to him. 672 * @hide 673 */ 674 public boolean selfAdded; 675 676 /** 677 * Set if the configuration was self added by the framework 678 * This boolean is set once and never cleared. It is used 679 * so as we never loose track of who created the 680 * configuration in the first place. 681 * @hide 682 */ 683 public boolean didSelfAdd; 684 685 /** 686 * Peer WifiConfiguration this WifiConfiguration was added for 687 * @hide 688 */ 689 public String peerWifiConfiguration; 690 691 /** 692 * @hide 693 * Indicate that a WifiConfiguration is temporary and should not be saved 694 * nor considered by AutoJoin. 695 */ 696 public boolean ephemeral; 697 698 /** 699 * @hide 700 * Indicate that we didn't auto-join because rssi was too low 701 */ 702 public boolean autoJoinBailedDueToLowRssi; 703 704 /** 705 * @hide 706 * AutoJoin even though RSSI is 10dB below threshold 707 */ 708 public int autoJoinUseAggressiveJoinAttemptThreshold; 709 710 /** 711 * @hide 712 * Number of time the scorer overrode a the priority based choice, when comparing two 713 * WifiConfigurations, note that since comparing WifiConfiguration happens very often 714 * potentially at every scan, this number might become very large, even on an idle 715 * system. 716 */ 717 @SystemApi 718 public int numScorerOverride; 719 720 /** 721 * @hide 722 * Number of time the scorer overrode a the priority based choice, and the comparison 723 * triggered a network switch 724 */ 725 @SystemApi 726 public int numScorerOverrideAndSwitchedNetwork; 727 728 /** 729 * @hide 730 * Number of time we associated to this configuration. 731 */ 732 @SystemApi 733 public int numAssociation; 734 735 /** 736 * @hide 737 * Number of time user disabled WiFi while associated to this configuration with Low RSSI. 738 */ 739 public int numUserTriggeredWifiDisableLowRSSI; 740 741 /** 742 * @hide 743 * Number of time user disabled WiFi while associated to this configuration with Bad RSSI. 744 */ 745 public int numUserTriggeredWifiDisableBadRSSI; 746 747 /** 748 * @hide 749 * Number of time user disabled WiFi while associated to this configuration 750 * and RSSI was not HIGH. 751 */ 752 public int numUserTriggeredWifiDisableNotHighRSSI; 753 754 /** 755 * @hide 756 * Number of ticks associated to this configuration with Low RSSI. 757 */ 758 public int numTicksAtLowRSSI; 759 760 /** 761 * @hide 762 * Number of ticks associated to this configuration with Bad RSSI. 763 */ 764 public int numTicksAtBadRSSI; 765 766 /** 767 * @hide 768 * Number of ticks associated to this configuration 769 * and RSSI was not HIGH. 770 */ 771 public int numTicksAtNotHighRSSI; 772 /** 773 * @hide 774 * Number of time user (WifiManager) triggered association to this configuration. 775 * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps 776 */ 777 public int numUserTriggeredJoinAttempts; 778 779 /** 780 * @hide 781 * Connect choices 782 * 783 * remember the keys identifying the known WifiConfiguration over which this configuration 784 * was preferred by user or a "WiFi Network Management app", that is, 785 * a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration 786 * was visible to the user: 787 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 788 * 789 * The integer represents the configuration's RSSI at that time (useful?) 790 * 791 * The overall auto-join algorithm make use of past connect choice so as to sort configuration, 792 * the exact algorithm still fluctuating as of 5/7/2014 793 * 794 */ 795 public HashMap<String, Integer> connectChoices; 796 797 /** 798 * @hide 799 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 800 * regarding roaming and auto-joining. 801 * The linked configuration may or may not have same SSID, and may or may not have same 802 * credentials. 803 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 804 */ 805 public HashMap<String, Integer> linkedConfigurations; 806 807 public WifiConfiguration() { 808 networkId = INVALID_NETWORK_ID; 809 SSID = null; 810 BSSID = null; 811 FQDN = null; 812 naiRealm = null; 813 priority = 0; 814 hiddenSSID = false; 815 disableReason = DISABLED_UNKNOWN_REASON; 816 allowedKeyManagement = new BitSet(); 817 allowedProtocols = new BitSet(); 818 allowedAuthAlgorithms = new BitSet(); 819 allowedPairwiseCiphers = new BitSet(); 820 allowedGroupCiphers = new BitSet(); 821 wepKeys = new String[4]; 822 for (int i = 0; i < wepKeys.length; i++) { 823 wepKeys[i] = null; 824 } 825 enterpriseConfig = new WifiEnterpriseConfig(); 826 autoJoinStatus = AUTO_JOIN_ENABLED; 827 selfAdded = false; 828 didSelfAdd = false; 829 ephemeral = false; 830 noInternetAccess = false; 831 mIpConfiguration = new IpConfiguration(); 832 } 833 834 /** 835 * indicates whether the configuration is valid 836 * @return true if valid, false otherwise 837 * @hide 838 */ 839 public boolean isValid() { 840 841 if (allowedKeyManagement == null) 842 return false; 843 844 if (allowedKeyManagement.cardinality() > 1) { 845 if (allowedKeyManagement.cardinality() != 2) { 846 return false; 847 } 848 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) { 849 return false; 850 } 851 if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false) 852 && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) { 853 return false; 854 } 855 } 856 857 // TODO: Add more checks 858 return true; 859 } 860 861 /** 862 * Helper function, identify if a configuration is linked 863 * @hide 864 */ 865 public boolean isLinked(WifiConfiguration config) { 866 if (config.linkedConfigurations != null && linkedConfigurations != null) { 867 if (config.linkedConfigurations.get(configKey()) != null 868 && linkedConfigurations.get(config.configKey()) != null) { 869 return true; 870 } 871 } 872 return false; 873 } 874 875 /** 876 * most recent time we have seen this configuration 877 * @return most recent scanResult 878 * @hide 879 */ 880 public ScanResult lastSeen() { 881 ScanResult mostRecent = null; 882 883 if (scanResultCache == null) { 884 return null; 885 } 886 887 for (ScanResult result : scanResultCache.values()) { 888 if (mostRecent == null) { 889 if (result.seen != 0) 890 mostRecent = result; 891 } else { 892 if (result.seen > mostRecent.seen) { 893 mostRecent = result; 894 } 895 } 896 } 897 return mostRecent; 898 } 899 900 /** @hide **/ 901 public void setAutoJoinStatus(int status) { 902 if (status < 0) status = 0; 903 if (status == 0) { 904 blackListTimestamp = 0; 905 } else if (status > autoJoinStatus) { 906 blackListTimestamp = System.currentTimeMillis(); 907 } 908 if (status != autoJoinStatus) { 909 autoJoinStatus = status; 910 dirty = true; 911 } 912 } 913 914 /* @hide */ 915 private ArrayList<ScanResult> sortScanResults() { 916 ArrayList<ScanResult> list = new ArrayList<ScanResult>(this.scanResultCache.values()); 917 if (list.size() != 0) { 918 Collections.sort(list, new Comparator() { 919 public int compare(Object o1, Object o2) { 920 ScanResult a = (ScanResult)o1; 921 ScanResult b = (ScanResult)o2; 922 if (a.numIpConfigFailures > b.numIpConfigFailures) { 923 return 1; 924 } 925 if (a.numIpConfigFailures < b.numIpConfigFailures) { 926 return -1; 927 } 928 if (a.seen > b.seen) { 929 return -1; 930 } 931 if (a.seen < b.seen) { 932 return 1; 933 } 934 if (a.level > b.level) { 935 return -1; 936 } 937 if (a.level < b.level) { 938 return 1; 939 } 940 return a.BSSID.compareTo(b.BSSID); 941 } 942 }); 943 } 944 return list; 945 } 946 947 @Override 948 public String toString() { 949 StringBuilder sbuf = new StringBuilder(); 950 if (this.status == WifiConfiguration.Status.CURRENT) { 951 sbuf.append("* "); 952 } else if (this.status == WifiConfiguration.Status.DISABLED) { 953 sbuf.append("- DSBLE "); 954 } 955 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 956 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN). 957 append(" REALM: ").append(this.naiRealm).append(" PRIO: ").append(this.priority). 958 append('\n'); 959 if (this.numConnectionFailures > 0) { 960 sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n"); 961 } 962 if (this.numIpConfigFailures > 0) { 963 sbuf.append(" numIpConfigFailures ").append(this.numIpConfigFailures).append("\n"); 964 } 965 if (this.numAuthFailures > 0) { 966 sbuf.append(" numAuthFailures ").append(this.numAuthFailures).append("\n"); 967 } 968 if (this.autoJoinStatus > 0) { 969 sbuf.append(" autoJoinStatus ").append(this.autoJoinStatus).append("\n"); 970 } 971 if (this.disableReason > 0) { 972 sbuf.append(" disableReason ").append(this.disableReason).append("\n"); 973 } 974 if (this.numAssociation > 0) { 975 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 976 } 977 if (this.didSelfAdd) sbuf.append(" didSelfAdd"); 978 if (this.selfAdded) sbuf.append(" selfAdded"); 979 if (this.noInternetAccess) sbuf.append(" noInternetAccess"); 980 if (this.didSelfAdd || this.selfAdded || this.noInternetAccess) { 981 sbuf.append("\n"); 982 } 983 sbuf.append(" KeyMgmt:"); 984 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 985 if (this.allowedKeyManagement.get(k)) { 986 sbuf.append(" "); 987 if (k < KeyMgmt.strings.length) { 988 sbuf.append(KeyMgmt.strings[k]); 989 } else { 990 sbuf.append("??"); 991 } 992 } 993 } 994 sbuf.append(" Protocols:"); 995 for (int p = 0; p < this.allowedProtocols.size(); p++) { 996 if (this.allowedProtocols.get(p)) { 997 sbuf.append(" "); 998 if (p < Protocol.strings.length) { 999 sbuf.append(Protocol.strings[p]); 1000 } else { 1001 sbuf.append("??"); 1002 } 1003 } 1004 } 1005 sbuf.append('\n'); 1006 sbuf.append(" AuthAlgorithms:"); 1007 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 1008 if (this.allowedAuthAlgorithms.get(a)) { 1009 sbuf.append(" "); 1010 if (a < AuthAlgorithm.strings.length) { 1011 sbuf.append(AuthAlgorithm.strings[a]); 1012 } else { 1013 sbuf.append("??"); 1014 } 1015 } 1016 } 1017 sbuf.append('\n'); 1018 sbuf.append(" PairwiseCiphers:"); 1019 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 1020 if (this.allowedPairwiseCiphers.get(pc)) { 1021 sbuf.append(" "); 1022 if (pc < PairwiseCipher.strings.length) { 1023 sbuf.append(PairwiseCipher.strings[pc]); 1024 } else { 1025 sbuf.append("??"); 1026 } 1027 } 1028 } 1029 sbuf.append('\n'); 1030 sbuf.append(" GroupCiphers:"); 1031 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 1032 if (this.allowedGroupCiphers.get(gc)) { 1033 sbuf.append(" "); 1034 if (gc < GroupCipher.strings.length) { 1035 sbuf.append(GroupCipher.strings[gc]); 1036 } else { 1037 sbuf.append("??"); 1038 } 1039 } 1040 } 1041 sbuf.append('\n').append(" PSK: "); 1042 if (this.preSharedKey != null) { 1043 sbuf.append('*'); 1044 } 1045 sbuf.append("\nEnterprise config:\n"); 1046 sbuf.append(enterpriseConfig); 1047 1048 sbuf.append("IP config:\n"); 1049 sbuf.append(mIpConfiguration.toString()); 1050 1051 if (this.creatorUid != 0) sbuf.append(" uid=" + Integer.toString(creatorUid)); 1052 if (this.autoJoinBSSID != null) sbuf.append(" autoJoinBSSID=" + autoJoinBSSID); 1053 long now_ms = System.currentTimeMillis(); 1054 if (this.blackListTimestamp != 0) { 1055 sbuf.append('\n'); 1056 long diff = now_ms - this.blackListTimestamp; 1057 if (diff <= 0) { 1058 sbuf.append(" blackListed since <incorrect>"); 1059 } else { 1060 sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec"); 1061 } 1062 } 1063 if (this.lastConnected != 0) { 1064 sbuf.append('\n'); 1065 long diff = now_ms - this.lastConnected; 1066 if (diff <= 0) { 1067 sbuf.append("lastConnected since <incorrect>"); 1068 } else { 1069 sbuf.append("lastConnected: ").append(Long.toString(diff/1000)).append( "sec"); 1070 } 1071 } 1072 if (this.lastConnectionFailure != 0) { 1073 sbuf.append('\n'); 1074 long diff = now_ms - this.lastConnectionFailure; 1075 if (diff <= 0) { 1076 sbuf.append("lastConnectionFailure since <incorrect>"); 1077 } else { 1078 sbuf.append("lastConnectionFailure: ").append(Long.toString(diff/1000)); 1079 sbuf.append( "sec"); 1080 } 1081 } 1082 sbuf.append('\n'); 1083 if (this.linkedConfigurations != null) { 1084 for(String key : this.linkedConfigurations.keySet()) { 1085 sbuf.append(" linked: ").append(key); 1086 sbuf.append('\n'); 1087 } 1088 } 1089 if (this.connectChoices != null) { 1090 for(String key : this.connectChoices.keySet()) { 1091 Integer choice = this.connectChoices.get(key); 1092 if (choice != null) { 1093 sbuf.append(" choice: ").append(key); 1094 sbuf.append(" = ").append(choice); 1095 sbuf.append('\n'); 1096 } 1097 } 1098 } 1099 if (this.scanResultCache != null) { 1100 sbuf.append("Scan Cache: ").append('\n'); 1101 ArrayList<ScanResult> list = sortScanResults(); 1102 if (list.size() > 0) { 1103 for (ScanResult result : list) { 1104 long milli = now_ms - result.seen; 1105 long ageSec = 0; 1106 long ageMin = 0; 1107 long ageHour = 0; 1108 long ageMilli = 0; 1109 long ageDay = 0; 1110 if (now_ms > result.seen && result.seen > 0) { 1111 ageMilli = milli % 1000; 1112 ageSec = (milli / 1000) % 60; 1113 ageMin = (milli / (60*1000)) % 60; 1114 ageHour = (milli / (60*60*1000)) % 24; 1115 ageDay = (milli / (24*60*60*1000)); 1116 } 1117 sbuf.append("{").append(result.BSSID).append(",").append(result.frequency); 1118 sbuf.append(",").append(String.format("%3d", result.level)); 1119 if (result.autoJoinStatus > 0) { 1120 sbuf.append(",st=").append(result.autoJoinStatus); 1121 } 1122 if (ageSec > 0 || ageMilli > 0) { 1123 sbuf.append(String.format(",%4d.%02d.%02d.%02d.%03dms", ageDay, 1124 ageHour, ageMin, ageSec, ageMilli)); 1125 } 1126 if (result.numIpConfigFailures > 0) { 1127 sbuf.append(",ipfail="); 1128 sbuf.append(result.numIpConfigFailures); 1129 } 1130 sbuf.append("} "); 1131 } 1132 sbuf.append('\n'); 1133 } 1134 } 1135 sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI); 1136 sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI); 1137 sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI); 1138 sbuf.append('\n'); 1139 sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI); 1140 sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI); 1141 sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI); 1142 sbuf.append('\n'); 1143 sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts); 1144 sbuf.append('\n'); 1145 sbuf.append("autoJoinBailedDueToLowRssi: ").append(this.autoJoinBailedDueToLowRssi); 1146 sbuf.append('\n'); 1147 sbuf.append("autoJoinUseAggressiveJoinAttemptThreshold: "); 1148 sbuf.append(this.autoJoinUseAggressiveJoinAttemptThreshold); 1149 sbuf.append('\n'); 1150 1151 return sbuf.toString(); 1152 } 1153 1154 /** 1155 * Construct a WifiConfiguration from a scanned network 1156 * @param scannedAP the scan result used to construct the config entry 1157 * TODO: figure out whether this is a useful way to construct a new entry. 1158 * 1159 public WifiConfiguration(ScanResult scannedAP) { 1160 networkId = -1; 1161 SSID = scannedAP.SSID; 1162 BSSID = scannedAP.BSSID; 1163 } 1164 */ 1165 1166 /** {@hide} */ 1167 public String getPrintableSsid() { 1168 if (SSID == null) return ""; 1169 final int length = SSID.length(); 1170 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 1171 return SSID.substring(1, length - 1); 1172 } 1173 1174 /** The ascii-encoded string format is P"<ascii-encoded-string>" 1175 * The decoding is implemented in the supplicant for a newly configured 1176 * network. 1177 */ 1178 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 1179 (SSID.charAt(length-1) == '"')) { 1180 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 1181 SSID.substring(2, length - 1)); 1182 return wifiSsid.toString(); 1183 } 1184 return SSID; 1185 } 1186 1187 /** 1188 * Get an identifier for associating credentials with this config 1189 * @param current configuration contains values for additional fields 1190 * that are not part of this configuration. Used 1191 * when a config with some fields is passed by an application. 1192 * @throws IllegalStateException if config is invalid for key id generation 1193 * @hide 1194 */ 1195 public String getKeyIdForCredentials(WifiConfiguration current) { 1196 String keyMgmt = null; 1197 1198 try { 1199 // Get current config details for fields that are not initialized 1200 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 1201 if (allowedKeyManagement.cardinality() == 0) { 1202 allowedKeyManagement = current.allowedKeyManagement; 1203 } 1204 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1205 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1206 } 1207 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1208 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 1209 } 1210 1211 if (TextUtils.isEmpty(keyMgmt)) { 1212 throw new IllegalStateException("Not an EAP network"); 1213 } 1214 1215 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 1216 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 1217 current.enterpriseConfig : null)); 1218 } catch (NullPointerException e) { 1219 throw new IllegalStateException("Invalid config details"); 1220 } 1221 } 1222 1223 private String trimStringForKeyId(String string) { 1224 // Remove quotes and spaces 1225 return string.replace("\"", "").replace(" ", ""); 1226 } 1227 1228 private static BitSet readBitSet(Parcel src) { 1229 int cardinality = src.readInt(); 1230 1231 BitSet set = new BitSet(); 1232 for (int i = 0; i < cardinality; i++) { 1233 set.set(src.readInt()); 1234 } 1235 1236 return set; 1237 } 1238 1239 private static void writeBitSet(Parcel dest, BitSet set) { 1240 int nextSetBit = -1; 1241 1242 dest.writeInt(set.cardinality()); 1243 1244 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1245 dest.writeInt(nextSetBit); 1246 } 1247 } 1248 1249 /** @hide */ 1250 public int getAuthType() { 1251 if (isValid() == false) { 1252 throw new IllegalStateException("Invalid configuration"); 1253 } 1254 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1255 return KeyMgmt.WPA_PSK; 1256 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 1257 return KeyMgmt.WPA2_PSK; 1258 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1259 return KeyMgmt.WPA_EAP; 1260 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1261 return KeyMgmt.IEEE8021X; 1262 } 1263 return KeyMgmt.NONE; 1264 } 1265 1266 /* @hide 1267 * Cache the config key, this seems useful as a speed up since a lot of 1268 * lookups in the config store are done and based on this key. 1269 */ 1270 String mCachedConfigKey; 1271 1272 /** @hide 1273 * return the string used to calculate the hash in WifiConfigStore 1274 * and uniquely identify this WifiConfiguration 1275 */ 1276 public String configKey(boolean allowCached) { 1277 String key; 1278 if (allowCached && mCachedConfigKey != null) { 1279 key = mCachedConfigKey; 1280 } else { 1281 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1282 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1283 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1284 allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1285 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1286 } else if (wepKeys[0] != null) { 1287 key = SSID + "WEP"; 1288 } else { 1289 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1290 } 1291 mCachedConfigKey = key; 1292 } 1293 return key; 1294 } 1295 1296 /** @hide 1297 * get configKey, force calculating the config string 1298 */ 1299 public String configKey() { 1300 return configKey(false); 1301 } 1302 1303 /** @hide 1304 * return the config key string based on a scan result 1305 */ 1306 static public String configKey(ScanResult result) { 1307 String key = "\"" + result.SSID + "\""; 1308 1309 if (result.capabilities.contains("WEP")) { 1310 key = key + "-WEP"; 1311 } 1312 1313 if (result.capabilities.contains("PSK")) { 1314 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1315 } 1316 1317 if (result.capabilities.contains("EAP")) { 1318 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1319 } 1320 1321 return key; 1322 } 1323 1324 /** @hide */ 1325 public IpConfiguration getIpConfiguration() { 1326 return mIpConfiguration; 1327 } 1328 1329 /** @hide */ 1330 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1331 mIpConfiguration = ipConfiguration; 1332 } 1333 1334 /** @hide */ 1335 public StaticIpConfiguration getStaticIpConfiguration() { 1336 return mIpConfiguration.getStaticIpConfiguration(); 1337 } 1338 1339 /** @hide */ 1340 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 1341 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 1342 } 1343 1344 /** @hide */ 1345 public IpConfiguration.IpAssignment getIpAssignment() { 1346 return mIpConfiguration.ipAssignment; 1347 } 1348 1349 /** @hide */ 1350 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1351 mIpConfiguration.ipAssignment = ipAssignment; 1352 } 1353 1354 /** @hide */ 1355 public IpConfiguration.ProxySettings getProxySettings() { 1356 return mIpConfiguration.proxySettings; 1357 } 1358 1359 /** @hide */ 1360 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1361 mIpConfiguration.proxySettings = proxySettings; 1362 } 1363 1364 /** @hide */ 1365 public ProxyInfo getHttpProxy() { 1366 return mIpConfiguration.httpProxy; 1367 } 1368 1369 /** @hide */ 1370 public void setHttpProxy(ProxyInfo httpProxy) { 1371 mIpConfiguration.httpProxy = httpProxy; 1372 } 1373 1374 /** @hide */ 1375 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1376 mIpConfiguration.proxySettings = settings; 1377 mIpConfiguration.httpProxy = proxy; 1378 } 1379 1380 /** Implement the Parcelable interface {@hide} */ 1381 public int describeContents() { 1382 return 0; 1383 } 1384 1385 /** copy constructor {@hide} */ 1386 public WifiConfiguration(WifiConfiguration source) { 1387 if (source != null) { 1388 networkId = source.networkId; 1389 status = source.status; 1390 disableReason = source.disableReason; 1391 disableReason = source.disableReason; 1392 SSID = source.SSID; 1393 BSSID = source.BSSID; 1394 FQDN = source.FQDN; 1395 naiRealm = source.naiRealm; 1396 preSharedKey = source.preSharedKey; 1397 1398 wepKeys = new String[4]; 1399 for (int i = 0; i < wepKeys.length; i++) { 1400 wepKeys[i] = source.wepKeys[i]; 1401 } 1402 1403 wepTxKeyIndex = source.wepTxKeyIndex; 1404 priority = source.priority; 1405 hiddenSSID = source.hiddenSSID; 1406 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 1407 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 1408 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 1409 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 1410 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 1411 1412 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 1413 1414 defaultGwMacAddress = source.defaultGwMacAddress; 1415 1416 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 1417 1418 if ((source.scanResultCache != null) && (source.scanResultCache.size() > 0)) { 1419 scanResultCache = new HashMap<String, ScanResult>(); 1420 scanResultCache.putAll(source.scanResultCache); 1421 } 1422 1423 if ((source.connectChoices != null) && (source.connectChoices.size() > 0)) { 1424 connectChoices = new HashMap<String, Integer>(); 1425 connectChoices.putAll(source.connectChoices); 1426 } 1427 1428 if ((source.linkedConfigurations != null) 1429 && (source.linkedConfigurations.size() > 0)) { 1430 linkedConfigurations = new HashMap<String, Integer>(); 1431 linkedConfigurations.putAll(source.linkedConfigurations); 1432 } 1433 mCachedConfigKey = null; //force null configKey 1434 autoJoinStatus = source.autoJoinStatus; 1435 selfAdded = source.selfAdded; 1436 noInternetAccess = source.noInternetAccess; 1437 if (source.visibility != null) { 1438 visibility = new Visibility(source.visibility); 1439 } 1440 1441 lastFailure = source.lastFailure; 1442 didSelfAdd = source.didSelfAdd; 1443 lastConnectUid = source.lastConnectUid; 1444 lastUpdateUid = source.lastUpdateUid; 1445 creatorUid = source.creatorUid; 1446 peerWifiConfiguration = source.peerWifiConfiguration; 1447 blackListTimestamp = source.blackListTimestamp; 1448 lastConnected = source.lastConnected; 1449 lastDisconnected = source.lastDisconnected; 1450 lastConnectionFailure = source.lastConnectionFailure; 1451 numConnectionFailures = source.numConnectionFailures; 1452 numIpConfigFailures = source.numIpConfigFailures; 1453 numAuthFailures = source.numAuthFailures; 1454 numScorerOverride = source.numScorerOverride; 1455 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 1456 numAssociation = source.numAssociation; 1457 numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI; 1458 numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI; 1459 numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI; 1460 numTicksAtLowRSSI = source.numTicksAtLowRSSI; 1461 numTicksAtBadRSSI = source.numTicksAtBadRSSI; 1462 numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI; 1463 numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts; 1464 autoJoinBSSID = source.autoJoinBSSID; 1465 autoJoinUseAggressiveJoinAttemptThreshold 1466 = source.autoJoinUseAggressiveJoinAttemptThreshold; 1467 autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi; 1468 dirty = source.dirty; 1469 } 1470 } 1471 1472 /** {@hide} */ 1473 //public static final int NOTHING_TAG = 0; 1474 /** {@hide} */ 1475 //public static final int SCAN_CACHE_TAG = 1; 1476 1477 /** Implement the Parcelable interface {@hide} */ 1478 @Override 1479 public void writeToParcel(Parcel dest, int flags) { 1480 dest.writeInt(networkId); 1481 dest.writeInt(status); 1482 dest.writeInt(disableReason); 1483 dest.writeString(SSID); 1484 dest.writeString(BSSID); 1485 dest.writeString(autoJoinBSSID); 1486 dest.writeString(FQDN); 1487 dest.writeString(naiRealm); 1488 dest.writeString(preSharedKey); 1489 for (String wepKey : wepKeys) { 1490 dest.writeString(wepKey); 1491 } 1492 dest.writeInt(wepTxKeyIndex); 1493 dest.writeInt(priority); 1494 dest.writeInt(hiddenSSID ? 1 : 0); 1495 dest.writeInt(requirePMF ? 1 : 0); 1496 dest.writeString(updateIdentifier); 1497 1498 writeBitSet(dest, allowedKeyManagement); 1499 writeBitSet(dest, allowedProtocols); 1500 writeBitSet(dest, allowedAuthAlgorithms); 1501 writeBitSet(dest, allowedPairwiseCiphers); 1502 writeBitSet(dest, allowedGroupCiphers); 1503 1504 dest.writeParcelable(enterpriseConfig, flags); 1505 1506 dest.writeParcelable(mIpConfiguration, flags); 1507 dest.writeString(dhcpServer); 1508 dest.writeString(defaultGwMacAddress); 1509 dest.writeInt(autoJoinStatus); 1510 dest.writeInt(selfAdded ? 1 : 0); 1511 dest.writeInt(didSelfAdd ? 1 : 0); 1512 dest.writeInt(noInternetAccess ? 1 : 0); 1513 dest.writeInt(creatorUid); 1514 dest.writeInt(lastConnectUid); 1515 dest.writeInt(lastUpdateUid); 1516 dest.writeLong(blackListTimestamp); 1517 dest.writeLong(lastConnectionFailure); 1518 dest.writeInt(numConnectionFailures); 1519 dest.writeInt(numIpConfigFailures); 1520 dest.writeInt(numAuthFailures); 1521 dest.writeInt(numScorerOverride); 1522 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 1523 dest.writeInt(numAssociation); 1524 dest.writeInt(numUserTriggeredWifiDisableLowRSSI); 1525 dest.writeInt(numUserTriggeredWifiDisableBadRSSI); 1526 dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI); 1527 dest.writeInt(numTicksAtLowRSSI); 1528 dest.writeInt(numTicksAtBadRSSI); 1529 dest.writeInt(numTicksAtNotHighRSSI); 1530 dest.writeInt(numUserTriggeredJoinAttempts); 1531 dest.writeInt(autoJoinUseAggressiveJoinAttemptThreshold); 1532 dest.writeInt(autoJoinBailedDueToLowRssi ? 1 : 0); 1533 } 1534 1535 /** Implement the Parcelable interface {@hide} */ 1536 public static final Creator<WifiConfiguration> CREATOR = 1537 new Creator<WifiConfiguration>() { 1538 public WifiConfiguration createFromParcel(Parcel in) { 1539 WifiConfiguration config = new WifiConfiguration(); 1540 config.networkId = in.readInt(); 1541 config.status = in.readInt(); 1542 config.disableReason = in.readInt(); 1543 config.SSID = in.readString(); 1544 config.BSSID = in.readString(); 1545 config.autoJoinBSSID = in.readString(); 1546 config.FQDN = in.readString(); 1547 config.naiRealm = in.readString(); 1548 config.preSharedKey = in.readString(); 1549 for (int i = 0; i < config.wepKeys.length; i++) { 1550 config.wepKeys[i] = in.readString(); 1551 } 1552 config.wepTxKeyIndex = in.readInt(); 1553 config.priority = in.readInt(); 1554 config.hiddenSSID = in.readInt() != 0; 1555 config.requirePMF = in.readInt() != 0; 1556 config.updateIdentifier = in.readString(); 1557 1558 config.allowedKeyManagement = readBitSet(in); 1559 config.allowedProtocols = readBitSet(in); 1560 config.allowedAuthAlgorithms = readBitSet(in); 1561 config.allowedPairwiseCiphers = readBitSet(in); 1562 config.allowedGroupCiphers = readBitSet(in); 1563 1564 config.enterpriseConfig = in.readParcelable(null); 1565 1566 config.mIpConfiguration = in.readParcelable(null); 1567 config.dhcpServer = in.readString(); 1568 config.defaultGwMacAddress = in.readString(); 1569 config.autoJoinStatus = in.readInt(); 1570 config.selfAdded = in.readInt() != 0; 1571 config.didSelfAdd = in.readInt() != 0; 1572 config.noInternetAccess = in.readInt() != 0; 1573 config.creatorUid = in.readInt(); 1574 config.lastConnectUid = in.readInt(); 1575 config.lastUpdateUid = in.readInt(); 1576 config.blackListTimestamp = in.readLong(); 1577 config.lastConnectionFailure = in.readLong(); 1578 config.numConnectionFailures = in.readInt(); 1579 config.numIpConfigFailures = in.readInt(); 1580 config.numAuthFailures = in.readInt(); 1581 config.numScorerOverride = in.readInt(); 1582 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 1583 config.numAssociation = in.readInt(); 1584 config.numUserTriggeredWifiDisableLowRSSI = in.readInt(); 1585 config.numUserTriggeredWifiDisableBadRSSI = in.readInt(); 1586 config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt(); 1587 config.numTicksAtLowRSSI = in.readInt(); 1588 config.numTicksAtBadRSSI = in.readInt(); 1589 config.numTicksAtNotHighRSSI = in.readInt(); 1590 config.numUserTriggeredJoinAttempts = in.readInt(); 1591 config.autoJoinUseAggressiveJoinAttemptThreshold = in.readInt(); 1592 config.autoJoinBailedDueToLowRssi = in.readInt() != 0; 1593 return config; 1594 } 1595 1596 public WifiConfiguration[] newArray(int size) { 1597 return new WifiConfiguration[size]; 1598 } 1599 }; 1600 } 1601