WifiConfiguration.java revision 2522c830a3ad3ae2ca7f675f13fafab8835d4f0c
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.net.IpConfiguration; 21import android.net.IpConfiguration.ProxySettings; 22import android.net.ProxyInfo; 23import android.net.StaticIpConfiguration; 24import android.os.Parcel; 25import android.os.Parcelable; 26import android.text.TextUtils; 27 28import java.util.HashMap; 29import java.util.BitSet; 30import java.util.ArrayList; 31import java.util.Collections; 32import java.util.Comparator; 33import java.util.HashSet; 34 35/** 36 * A class representing a configured Wi-Fi network, including the 37 * security configuration. 38 */ 39public class WifiConfiguration implements Parcelable { 40 private static final String TAG = "WifiConfiguration"; 41 /** {@hide} */ 42 public static final String ssidVarName = "ssid"; 43 /** {@hide} */ 44 public static final String bssidVarName = "bssid"; 45 /** {@hide} */ 46 public static final String pskVarName = "psk"; 47 /** {@hide} */ 48 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 49 /** {@hide} */ 50 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 51 /** {@hide} */ 52 public static final String priorityVarName = "priority"; 53 /** {@hide} */ 54 public static final String hiddenSSIDVarName = "scan_ssid"; 55 /** {@hide} */ 56 public static final String pmfVarName = "ieee80211w"; 57 /** {@hide} */ 58 public static final String updateIdentiferVarName = "update_identifier"; 59 /** {@hide} */ 60 public static final int INVALID_NETWORK_ID = -1; 61 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 /** 238 * The band which AP resides on 239 * 0-2G 1-5G 240 * By default, 2G is chosen 241 */ 242 public int apBand = 0; 243 244 /** 245 * The channel which AP resides on,currently, US only 246 * 2G 1-11 247 * 5G 36,40,44,48,149,153,157,161,165 248 * 0 - find a random available channel according to the apBand 249 */ 250 public int apChannel = 0; 251 252 /** 253 * Pre-shared key for use with WPA-PSK. 254 * <p/> 255 * When the value of this key is read, the actual key is 256 * not returned, just a "*" if the key has a value, or the null 257 * string otherwise. 258 */ 259 public String preSharedKey; 260 /** 261 * Up to four WEP keys. Either an ASCII string enclosed in double 262 * quotation marks (e.g., {@code "abcdef"} or a string 263 * of hex digits (e.g., {@code 0102030405}). 264 * <p/> 265 * When the value of one of these keys is read, the actual key is 266 * not returned, just a "*" if the key has a value, or the null 267 * string otherwise. 268 */ 269 public String[] wepKeys; 270 271 /** Default WEP key index, ranging from 0 to 3. */ 272 public int wepTxKeyIndex; 273 274 /** 275 * Priority determines the preference given to a network by {@code wpa_supplicant} 276 * when choosing an access point with which to associate. 277 */ 278 public int priority; 279 280 /** 281 * This is a network that does not broadcast its SSID, so an 282 * SSID-specific probe request must be used for scans. 283 */ 284 public boolean hiddenSSID; 285 286 /** 287 * This is a network that requries Protected Management Frames (PMF). 288 * @hide 289 */ 290 public boolean requirePMF; 291 292 /** 293 * Update identifier, for Passpoint network. 294 * @hide 295 */ 296 public String updateIdentifier; 297 298 /** 299 * The set of key management protocols supported by this configuration. 300 * See {@link KeyMgmt} for descriptions of the values. 301 * Defaults to WPA-PSK WPA-EAP. 302 */ 303 public BitSet allowedKeyManagement; 304 /** 305 * The set of security protocols supported by this configuration. 306 * See {@link Protocol} for descriptions of the values. 307 * Defaults to WPA RSN. 308 */ 309 public BitSet allowedProtocols; 310 /** 311 * The set of authentication protocols supported by this configuration. 312 * See {@link AuthAlgorithm} for descriptions of the values. 313 * Defaults to automatic selection. 314 */ 315 public BitSet allowedAuthAlgorithms; 316 /** 317 * The set of pairwise ciphers for WPA supported by this configuration. 318 * See {@link PairwiseCipher} for descriptions of the values. 319 * Defaults to CCMP TKIP. 320 */ 321 public BitSet allowedPairwiseCiphers; 322 /** 323 * The set of group ciphers supported by this configuration. 324 * See {@link GroupCipher} for descriptions of the values. 325 * Defaults to CCMP TKIP WEP104 WEP40. 326 */ 327 public BitSet allowedGroupCiphers; 328 /** 329 * The enterprise configuration details specifying the EAP method, 330 * certificates and other settings associated with the EAP. 331 */ 332 public WifiEnterpriseConfig enterpriseConfig; 333 334 /** 335 * Fully qualified domain name of a passpoint configuration 336 */ 337 public String FQDN; 338 339 /** 340 * Service provider name, for Passpoint credential. 341 */ 342 public String providerFriendlyName; 343 344 /** 345 * Roaming Consortium Id, for Passpoint credential. 346 */ 347 public HashSet<Long> roamingConsortiumIds; 348 349 /** 350 * @hide 351 */ 352 private IpConfiguration mIpConfiguration; 353 354 /** 355 * @hide 356 * dhcp server MAC address if known 357 */ 358 public String dhcpServer; 359 360 /** 361 * @hide 362 * default Gateway MAC address if known 363 */ 364 public String defaultGwMacAddress; 365 366 /** 367 * @hide 368 * last failure 369 */ 370 public String lastFailure; 371 372 /** 373 * @hide 374 * last time we connected, this configuration had validated internet access 375 */ 376 public boolean validatedInternetAccess; 377 378 /** 379 * @hide 380 * Uid of app creating the configuration 381 */ 382 @SystemApi 383 public int creatorUid; 384 385 /** 386 * @hide 387 * Uid of last app issuing a connection related command 388 */ 389 public int lastConnectUid; 390 391 /** 392 * @hide 393 * Uid of last app modifying the configuration 394 */ 395 @SystemApi 396 public int lastUpdateUid; 397 398 /** 399 * @hide 400 * Uid used by autoJoin 401 */ 402 public String autoJoinBSSID; 403 404 /** 405 * @hide 406 * BSSID list on which this configuration was seen. 407 * TODO: prevent this list to grow infinitely, age-out the results 408 */ 409 public HashMap<String, ScanResult> scanResultCache; 410 411 /** The Below RSSI thresholds are used to configure AutoJoin 412 * - GOOD/LOW/BAD thresholds are used so as to calculate link score 413 * - UNWANTED_SOFT are used by the blacklisting logic so as to handle 414 * the unwanted network message coming from CS 415 * - UNBLACKLIST thresholds are used so as to tweak the speed at which 416 * the network is unblacklisted (i.e. if 417 * it is seen with good RSSI, it is blacklisted faster) 418 * - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from 419 * the network we need to be before autojoin kicks in 420 */ 421 /** @hide **/ 422 public static int INVALID_RSSI = -127; 423 424 /** @hide **/ 425 public static int UNWANTED_BLACKLIST_SOFT_RSSI_24 = -80; 426 427 /** @hide **/ 428 public static int UNWANTED_BLACKLIST_SOFT_RSSI_5 = -70; 429 430 /** @hide **/ 431 public static int GOOD_RSSI_24 = -65; 432 433 /** @hide **/ 434 public static int LOW_RSSI_24 = -77; 435 436 /** @hide **/ 437 public static int BAD_RSSI_24 = -87; 438 439 /** @hide **/ 440 public static int GOOD_RSSI_5 = -60; 441 442 /** @hide **/ 443 public static int LOW_RSSI_5 = -72; 444 445 /** @hide **/ 446 public static int BAD_RSSI_5 = -82; 447 448 /** @hide **/ 449 public static int UNWANTED_BLACKLIST_SOFT_BUMP = 4; 450 451 /** @hide **/ 452 public static int UNWANTED_BLACKLIST_HARD_BUMP = 8; 453 454 /** @hide **/ 455 public static int UNBLACKLIST_THRESHOLD_24_SOFT = -77; 456 457 /** @hide **/ 458 public static int UNBLACKLIST_THRESHOLD_24_HARD = -68; 459 460 /** @hide **/ 461 public static int UNBLACKLIST_THRESHOLD_5_SOFT = -63; 462 463 /** @hide **/ 464 public static int UNBLACKLIST_THRESHOLD_5_HARD = -56; 465 466 /** @hide **/ 467 public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_24 = -80; 468 469 /** @hide **/ 470 public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_5 = -70; 471 472 /** @hide 473 * 5GHz band is prefered low over 2.4 if the 5GHz RSSI is higher than this threshold */ 474 public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65; 475 476 /** @hide 477 * 5GHz band is penalized if the 5GHz RSSI is lower than this threshold **/ 478 public static int G_BAND_PREFERENCE_RSSI_THRESHOLD = -75; 479 480 /** @hide 481 * Boost given to RSSI on a home network for the purpose of calculating the score 482 * This adds stickiness to home networks, as defined by: 483 * - less than 4 known BSSIDs 484 * - PSK only 485 * - TODO: add a test to verify that all BSSIDs are behind same gateway 486 ***/ 487 public static int HOME_NETWORK_RSSI_BOOST = 5; 488 489 /** @hide 490 * RSSI boost for configuration which use autoJoinUseAggressiveJoinAttemptThreshold 491 * To be more aggressive when initially attempting to auto join 492 */ 493 public static int MAX_INITIAL_AUTO_JOIN_RSSI_BOOST = 8; 494 495 /** 496 * @hide 497 * A summary of the RSSI and Band status for that configuration 498 * This is used as a temporary value by the auto-join controller 499 */ 500 public final class Visibility { 501 public int rssi5; // strongest 5GHz RSSI 502 public int rssi24; // strongest 2.4GHz RSSI 503 public int num5; // number of BSSIDs on 5GHz 504 public int num24; // number of BSSIDs on 2.4GHz 505 public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen) 506 public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen) 507 public String BSSID24; 508 public String BSSID5; 509 public int score; // Debug only, indicate last score used for autojoin/cell-handover 510 public int currentNetworkBoost; // Debug only, indicate boost applied to RSSI if current 511 public int bandPreferenceBoost; // Debug only, indicate boost applied to RSSI if current 512 public int lastChoiceBoost; // Debug only, indicate last choice applied to this configuration 513 public String lastChoiceConfig; // Debug only, indicate last choice applied to this configuration 514 515 public Visibility() { 516 rssi5 = INVALID_RSSI; 517 rssi24 = INVALID_RSSI; 518 } 519 520 public Visibility(Visibility source) { 521 rssi5 = source.rssi5; 522 rssi24 = source.rssi24; 523 age24 = source.age24; 524 age5 = source.age5; 525 num24 = source.num24; 526 num5 = source.num5; 527 BSSID5 = source.BSSID5; 528 BSSID24 = source.BSSID24; 529 } 530 531 @Override 532 public String toString() { 533 StringBuilder sbuf = new StringBuilder(); 534 sbuf.append("["); 535 if (rssi24 > INVALID_RSSI) { 536 sbuf.append(Integer.toString(rssi24)); 537 sbuf.append(","); 538 sbuf.append(Integer.toString(num24)); 539 if (BSSID24 != null) sbuf.append(",").append(BSSID24); 540 } 541 sbuf.append("; "); 542 if (rssi5 > INVALID_RSSI) { 543 sbuf.append(Integer.toString(rssi5)); 544 sbuf.append(","); 545 sbuf.append(Integer.toString(num5)); 546 if (BSSID5 != null) sbuf.append(",").append(BSSID5); 547 } 548 if (score != 0) { 549 sbuf.append("; ").append(score); 550 sbuf.append(", ").append(currentNetworkBoost); 551 sbuf.append(", ").append(bandPreferenceBoost); 552 if (lastChoiceConfig != null) { 553 sbuf.append(", ").append(lastChoiceBoost); 554 sbuf.append(", ").append(lastChoiceConfig); 555 } 556 } 557 sbuf.append("]"); 558 return sbuf.toString(); 559 } 560 } 561 562 /** @hide 563 * Cache the visibility status of this configuration. 564 * Visibility can change at any time depending on scan results availability. 565 * Owner of the WifiConfiguration is responsible to set this field based on 566 * recent scan results. 567 ***/ 568 public Visibility visibility; 569 570 /** @hide 571 * calculate and set Visibility for that configuration. 572 * 573 * age in milliseconds: we will consider only ScanResults that are more recent, 574 * i.e. younger. 575 ***/ 576 public Visibility setVisibility(long age) { 577 if (scanResultCache == null) { 578 visibility = null; 579 return null; 580 } 581 582 Visibility status = new Visibility(); 583 584 long now_ms = System.currentTimeMillis(); 585 for(ScanResult result : scanResultCache.values()) { 586 if (result.seen == 0) 587 continue; 588 589 if (result.is5GHz()) { 590 //strictly speaking: [4915, 5825] 591 //number of known BSSID on 5GHz band 592 status.num5 = status.num5 + 1; 593 } else if (result.is24GHz()) { 594 //strictly speaking: [2412, 2482] 595 //number of known BSSID on 2.4Ghz band 596 status.num24 = status.num24 + 1; 597 } 598 599 if ((now_ms - result.seen) > age) continue; 600 601 if (result.is5GHz()) { 602 if (result.level > status.rssi5) { 603 status.rssi5 = result.level; 604 status.age5 = result.seen; 605 status.BSSID5 = result.BSSID; 606 } 607 } else if (result.is24GHz()) { 608 if (result.level > status.rssi24) { 609 status.rssi24 = result.level; 610 status.age24 = result.seen; 611 status.BSSID24 = result.BSSID; 612 } 613 } 614 } 615 visibility = status; 616 return status; 617 } 618 619 /** @hide */ 620 public static final int AUTO_JOIN_ENABLED = 0; 621 /** 622 * if this is set, the WifiConfiguration cannot use linkages so as to bump 623 * it's relative priority. 624 * - status between and 128 indicate various level of blacklisting depending 625 * on the severity or frequency of the connection error 626 * - deleted status indicates that the user is deleting the configuration, and so 627 * although it may have been self added we will not re-self-add it, ignore it, 628 * not return it to applications, and not connect to it 629 * */ 630 631 /** @hide 632 * network was temporary disabled due to bad connection, most likely due 633 * to weak RSSI */ 634 public static final int AUTO_JOIN_TEMPORARY_DISABLED = 1; 635 /** @hide 636 * network was temporary disabled due to bad connection, which cant be attributed 637 * to weak RSSI */ 638 public static final int AUTO_JOIN_TEMPORARY_DISABLED_LINK_ERRORS = 32; 639 /** @hide */ 640 public static final int AUTO_JOIN_TEMPORARY_DISABLED_AT_SUPPLICANT = 64; 641 /** @hide */ 642 public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE = 128; 643 /** @hide */ 644 public static final int AUTO_JOIN_DISABLED_NO_CREDENTIALS = 160; 645 /** @hide */ 646 public static final int AUTO_JOIN_DISABLED_USER_ACTION = 161; 647 648 /** @hide */ 649 public static final int AUTO_JOIN_DELETED = 200; 650 651 /** 652 * @hide 653 */ 654 public int autoJoinStatus; 655 656 /** 657 * @hide 658 * Number of connection failures 659 */ 660 public int numConnectionFailures; 661 662 /** 663 * @hide 664 * Number of IP config failures 665 */ 666 public int numIpConfigFailures; 667 668 /** 669 * @hide 670 * Number of Auth failures 671 */ 672 public int numAuthFailures; 673 674 /** 675 * @hide 676 * Number of reports indicating no Internet Access 677 */ 678 public int numNoInternetAccessReports; 679 680 /** 681 * @hide 682 * The WiFi configuration is considered to have no internet access for purpose of autojoining 683 * if there has been a report of it having no internet access, and, it never have had 684 * internet access in the past. 685 */ 686 public boolean hasNoInternetAccess() { 687 return numNoInternetAccessReports > 0 && !validatedInternetAccess; 688 } 689 690 /** 691 * @hide 692 * Last time we blacklisted the configuration 693 */ 694 public long blackListTimestamp; 695 696 /** 697 * @hide 698 * Last time the system was connected to this configuration. 699 */ 700 public long lastConnected; 701 702 /** 703 * @hide 704 * Last time the system tried to connect and failed. 705 */ 706 public long lastConnectionFailure; 707 708 /** 709 * @hide 710 * Last time the system tried to roam and failed because of authentication failure or DHCP 711 * RENEW failure. 712 */ 713 public long lastRoamingFailure; 714 715 /** @hide */ 716 public static int ROAMING_FAILURE_IP_CONFIG = 1; 717 /** @hide */ 718 public static int ROAMING_FAILURE_AUTH_FAILURE = 2; 719 720 /** 721 * @hide 722 * Initial amount of time this Wifi configuration gets blacklisted for network switching 723 * because of roaming failure 724 */ 725 public long roamingFailureBlackListTimeMilli = 1000; 726 727 /** 728 * @hide 729 * Last roaming failure reason code 730 */ 731 public int lastRoamingFailureReason; 732 733 /** 734 * @hide 735 * Last time the system was disconnected to this configuration. 736 */ 737 public long lastDisconnected; 738 739 /** 740 * Set if the configuration was self added by the framework 741 * This boolean is cleared if we get a connect/save/ update or 742 * any wifiManager command that indicate the user interacted with the configuration 743 * since we will now consider that the configuration belong to him. 744 * @hide 745 */ 746 public boolean selfAdded; 747 748 /** 749 * Set if the configuration was self added by the framework 750 * This boolean is set once and never cleared. It is used 751 * so as we never loose track of who created the 752 * configuration in the first place. 753 * @hide 754 */ 755 public boolean didSelfAdd; 756 757 /** 758 * Peer WifiConfiguration this WifiConfiguration was added for 759 * @hide 760 */ 761 public String peerWifiConfiguration; 762 763 /** 764 * @hide 765 * Indicate that a WifiConfiguration is temporary and should not be saved 766 * nor considered by AutoJoin. 767 */ 768 public boolean ephemeral; 769 770 /** 771 * @hide 772 * Indicate that we didn't auto-join because rssi was too low 773 */ 774 public boolean autoJoinBailedDueToLowRssi; 775 776 /** 777 * @hide 778 * AutoJoin even though RSSI is 10dB below threshold 779 */ 780 public int autoJoinUseAggressiveJoinAttemptThreshold; 781 782 /** 783 * @hide 784 * Number of time the scorer overrode a the priority based choice, when comparing two 785 * WifiConfigurations, note that since comparing WifiConfiguration happens very often 786 * potentially at every scan, this number might become very large, even on an idle 787 * system. 788 */ 789 @SystemApi 790 public int numScorerOverride; 791 792 /** 793 * @hide 794 * Number of time the scorer overrode a the priority based choice, and the comparison 795 * triggered a network switch 796 */ 797 @SystemApi 798 public int numScorerOverrideAndSwitchedNetwork; 799 800 /** 801 * @hide 802 * Number of time we associated to this configuration. 803 */ 804 @SystemApi 805 public int numAssociation; 806 807 /** 808 * @hide 809 * Number of time user disabled WiFi while associated to this configuration with Low RSSI. 810 */ 811 public int numUserTriggeredWifiDisableLowRSSI; 812 813 /** 814 * @hide 815 * Number of time user disabled WiFi while associated to this configuration with Bad RSSI. 816 */ 817 public int numUserTriggeredWifiDisableBadRSSI; 818 819 /** 820 * @hide 821 * Number of time user disabled WiFi while associated to this configuration 822 * and RSSI was not HIGH. 823 */ 824 public int numUserTriggeredWifiDisableNotHighRSSI; 825 826 /** 827 * @hide 828 * Number of ticks associated to this configuration with Low RSSI. 829 */ 830 public int numTicksAtLowRSSI; 831 832 /** 833 * @hide 834 * Number of ticks associated to this configuration with Bad RSSI. 835 */ 836 public int numTicksAtBadRSSI; 837 838 /** 839 * @hide 840 * Number of ticks associated to this configuration 841 * and RSSI was not HIGH. 842 */ 843 public int numTicksAtNotHighRSSI; 844 /** 845 * @hide 846 * Number of time user (WifiManager) triggered association to this configuration. 847 * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps 848 */ 849 public int numUserTriggeredJoinAttempts; 850 851 /** 852 * @hide 853 * Connect choices 854 * 855 * remember the keys identifying the known WifiConfiguration over which this configuration 856 * was preferred by user or a "WiFi Network Management app", that is, 857 * a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration 858 * was visible to the user: 859 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 860 * 861 * The integer represents the configuration's RSSI at that time (useful?) 862 * 863 * The overall auto-join algorithm make use of past connect choice so as to sort configuration, 864 * the exact algorithm still fluctuating as of 5/7/2014 865 * 866 */ 867 public HashMap<String, Integer> connectChoices; 868 869 /** 870 * @hide 871 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 872 * regarding roaming and auto-joining. 873 * The linked configuration may or may not have same SSID, and may or may not have same 874 * credentials. 875 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 876 */ 877 public HashMap<String, Integer> linkedConfigurations; 878 879 public WifiConfiguration() { 880 networkId = INVALID_NETWORK_ID; 881 SSID = null; 882 BSSID = null; 883 FQDN = null; 884 roamingConsortiumIds = new HashSet<Long>(); 885 priority = 0; 886 hiddenSSID = false; 887 disableReason = DISABLED_UNKNOWN_REASON; 888 allowedKeyManagement = new BitSet(); 889 allowedProtocols = new BitSet(); 890 allowedAuthAlgorithms = new BitSet(); 891 allowedPairwiseCiphers = new BitSet(); 892 allowedGroupCiphers = new BitSet(); 893 wepKeys = new String[4]; 894 for (int i = 0; i < wepKeys.length; i++) { 895 wepKeys[i] = null; 896 } 897 enterpriseConfig = new WifiEnterpriseConfig(); 898 autoJoinStatus = AUTO_JOIN_ENABLED; 899 selfAdded = false; 900 didSelfAdd = false; 901 ephemeral = false; 902 validatedInternetAccess = false; 903 mIpConfiguration = new IpConfiguration(); 904 } 905 906 /** 907 * indicates whether the configuration is valid 908 * @return true if valid, false otherwise 909 * @hide 910 */ 911 public boolean isValid() { 912 913 if (allowedKeyManagement == null) 914 return false; 915 916 if (allowedKeyManagement.cardinality() > 1) { 917 if (allowedKeyManagement.cardinality() != 2) { 918 return false; 919 } 920 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) { 921 return false; 922 } 923 if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false) 924 && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) { 925 return false; 926 } 927 } 928 929 if (TextUtils.isEmpty(FQDN) == false) { 930 /* this is passpoint configuration; it must not have an SSID */ 931 if (TextUtils.isEmpty(SSID) == false) { 932 return false; 933 } 934 /* this is passpoint configuration; it must have a providerFriendlyName */ 935 if (TextUtils.isEmpty(providerFriendlyName)) { 936 return false; 937 } 938 /* this is passpoint configuration; it must have enterprise config */ 939 if (enterpriseConfig == null 940 || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { 941 return false; 942 } 943 } 944 945 // TODO: Add more checks 946 return true; 947 } 948 949 /** 950 * Identify if this configuration represents a passpoint network 951 */ 952 public boolean isPasspoint() { 953 return TextUtils.isEmpty(SSID) 954 && !TextUtils.isEmpty(FQDN) 955 && !TextUtils.isEmpty(providerFriendlyName) 956 && enterpriseConfig != null 957 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 958 } 959 960 /** 961 * Helper function, identify if a configuration is linked 962 * @hide 963 */ 964 public boolean isLinked(WifiConfiguration config) { 965 if (config.linkedConfigurations != null && linkedConfigurations != null) { 966 if (config.linkedConfigurations.get(configKey()) != null 967 && linkedConfigurations.get(config.configKey()) != null) { 968 return true; 969 } 970 } 971 return false; 972 } 973 974 /** 975 * most recent time we have seen this configuration 976 * @return most recent scanResult 977 * @hide 978 */ 979 public ScanResult lastSeen() { 980 ScanResult mostRecent = null; 981 982 if (scanResultCache == null) { 983 return null; 984 } 985 986 for (ScanResult result : scanResultCache.values()) { 987 if (mostRecent == null) { 988 if (result.seen != 0) 989 mostRecent = result; 990 } else { 991 if (result.seen > mostRecent.seen) { 992 mostRecent = result; 993 } 994 } 995 } 996 return mostRecent; 997 } 998 999 /** @hide **/ 1000 public void setAutoJoinStatus(int status) { 1001 if (status < 0) status = 0; 1002 if (status == 0) { 1003 blackListTimestamp = 0; 1004 } else if (status > autoJoinStatus) { 1005 blackListTimestamp = System.currentTimeMillis(); 1006 } 1007 if (status != autoJoinStatus) { 1008 autoJoinStatus = status; 1009 dirty = true; 1010 } 1011 } 1012 1013 /** @hide 1014 * trim the scan Result Cache 1015 * @param: number of entries to keep in the cache 1016 */ 1017 public void trimScanResultsCache(int num) { 1018 if (this.scanResultCache == null) { 1019 return; 1020 } 1021 int currenSize = this.scanResultCache.size(); 1022 if (currenSize <= num) { 1023 return; // Nothing to trim 1024 } 1025 ArrayList<ScanResult> list = new ArrayList<ScanResult>(this.scanResultCache.values()); 1026 if (list.size() != 0) { 1027 // Sort by descending timestamp 1028 Collections.sort(list, new Comparator() { 1029 public int compare(Object o1, Object o2) { 1030 ScanResult a = (ScanResult)o1; 1031 ScanResult b = (ScanResult)o2; 1032 if (a.seen > b.seen) { 1033 return 1; 1034 } 1035 if (a.seen < b.seen) { 1036 return -1; 1037 } 1038 return a.BSSID.compareTo(b.BSSID); 1039 } 1040 }); 1041 } 1042 for (int i = 0; i < currenSize - num ; i++) { 1043 // Remove oldest results from scan cache 1044 ScanResult result = list.get(i); 1045 this.scanResultCache.remove(result.BSSID); 1046 } 1047 } 1048 1049 /* @hide */ 1050 private ArrayList<ScanResult> sortScanResults() { 1051 ArrayList<ScanResult> list = new ArrayList<ScanResult>(this.scanResultCache.values()); 1052 if (list.size() != 0) { 1053 Collections.sort(list, new Comparator() { 1054 public int compare(Object o1, Object o2) { 1055 ScanResult a = (ScanResult)o1; 1056 ScanResult b = (ScanResult)o2; 1057 if (a.numIpConfigFailures > b.numIpConfigFailures) { 1058 return 1; 1059 } 1060 if (a.numIpConfigFailures < b.numIpConfigFailures) { 1061 return -1; 1062 } 1063 if (a.seen > b.seen) { 1064 return -1; 1065 } 1066 if (a.seen < b.seen) { 1067 return 1; 1068 } 1069 if (a.level > b.level) { 1070 return -1; 1071 } 1072 if (a.level < b.level) { 1073 return 1; 1074 } 1075 return a.BSSID.compareTo(b.BSSID); 1076 } 1077 }); 1078 } 1079 return list; 1080 } 1081 1082 @Override 1083 public String toString() { 1084 StringBuilder sbuf = new StringBuilder(); 1085 if (this.status == WifiConfiguration.Status.CURRENT) { 1086 sbuf.append("* "); 1087 } else if (this.status == WifiConfiguration.Status.DISABLED) { 1088 sbuf.append("- DSBLE "); 1089 } 1090 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 1091 append(" PROVIDER-NAME: ").append(this.providerFriendlyName). 1092 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN). 1093 append(" PRIO: ").append(this.priority). 1094 append('\n'); 1095 if (this.numConnectionFailures > 0) { 1096 sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n"); 1097 } 1098 if (this.numIpConfigFailures > 0) { 1099 sbuf.append(" numIpConfigFailures ").append(this.numIpConfigFailures).append("\n"); 1100 } 1101 if (this.numAuthFailures > 0) { 1102 sbuf.append(" numAuthFailures ").append(this.numAuthFailures).append("\n"); 1103 } 1104 if (this.autoJoinStatus > 0) { 1105 sbuf.append(" autoJoinStatus ").append(this.autoJoinStatus).append("\n"); 1106 } 1107 if (this.disableReason > 0) { 1108 sbuf.append(" disableReason ").append(this.disableReason).append("\n"); 1109 } 1110 if (this.numAssociation > 0) { 1111 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 1112 } 1113 if (this.numNoInternetAccessReports > 0) { 1114 sbuf.append(" numNoInternetAccessReports "); 1115 sbuf.append(this.numNoInternetAccessReports).append("\n"); 1116 } 1117 if (this.didSelfAdd) sbuf.append(" didSelfAdd"); 1118 if (this.selfAdded) sbuf.append(" selfAdded"); 1119 if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); 1120 if (this.ephemeral) sbuf.append(" ephemeral"); 1121 if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess || this.ephemeral) { 1122 sbuf.append("\n"); 1123 } 1124 sbuf.append(" KeyMgmt:"); 1125 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 1126 if (this.allowedKeyManagement.get(k)) { 1127 sbuf.append(" "); 1128 if (k < KeyMgmt.strings.length) { 1129 sbuf.append(KeyMgmt.strings[k]); 1130 } else { 1131 sbuf.append("??"); 1132 } 1133 } 1134 } 1135 sbuf.append(" Protocols:"); 1136 for (int p = 0; p < this.allowedProtocols.size(); p++) { 1137 if (this.allowedProtocols.get(p)) { 1138 sbuf.append(" "); 1139 if (p < Protocol.strings.length) { 1140 sbuf.append(Protocol.strings[p]); 1141 } else { 1142 sbuf.append("??"); 1143 } 1144 } 1145 } 1146 sbuf.append('\n'); 1147 sbuf.append(" AuthAlgorithms:"); 1148 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 1149 if (this.allowedAuthAlgorithms.get(a)) { 1150 sbuf.append(" "); 1151 if (a < AuthAlgorithm.strings.length) { 1152 sbuf.append(AuthAlgorithm.strings[a]); 1153 } else { 1154 sbuf.append("??"); 1155 } 1156 } 1157 } 1158 sbuf.append('\n'); 1159 sbuf.append(" PairwiseCiphers:"); 1160 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 1161 if (this.allowedPairwiseCiphers.get(pc)) { 1162 sbuf.append(" "); 1163 if (pc < PairwiseCipher.strings.length) { 1164 sbuf.append(PairwiseCipher.strings[pc]); 1165 } else { 1166 sbuf.append("??"); 1167 } 1168 } 1169 } 1170 sbuf.append('\n'); 1171 sbuf.append(" GroupCiphers:"); 1172 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 1173 if (this.allowedGroupCiphers.get(gc)) { 1174 sbuf.append(" "); 1175 if (gc < GroupCipher.strings.length) { 1176 sbuf.append(GroupCipher.strings[gc]); 1177 } else { 1178 sbuf.append("??"); 1179 } 1180 } 1181 } 1182 sbuf.append('\n').append(" PSK: "); 1183 if (this.preSharedKey != null) { 1184 sbuf.append('*'); 1185 } 1186 sbuf.append("\nEnterprise config:\n"); 1187 sbuf.append(enterpriseConfig); 1188 1189 sbuf.append("IP config:\n"); 1190 sbuf.append(mIpConfiguration.toString()); 1191 1192 if (this.creatorUid != 0) sbuf.append(" uid=" + Integer.toString(creatorUid)); 1193 if (this.autoJoinBSSID != null) sbuf.append(" autoJoinBSSID=" + autoJoinBSSID); 1194 long now_ms = System.currentTimeMillis(); 1195 if (this.blackListTimestamp != 0) { 1196 sbuf.append('\n'); 1197 long diff = now_ms - this.blackListTimestamp; 1198 if (diff <= 0) { 1199 sbuf.append(" blackListed since <incorrect>"); 1200 } else { 1201 sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec"); 1202 } 1203 } 1204 if (this.lastConnected != 0) { 1205 sbuf.append('\n'); 1206 long diff = now_ms - this.lastConnected; 1207 if (diff <= 0) { 1208 sbuf.append("lastConnected since <incorrect>"); 1209 } else { 1210 sbuf.append("lastConnected: ").append(Long.toString(diff/1000)).append( "sec"); 1211 } 1212 } 1213 if (this.lastConnectionFailure != 0) { 1214 sbuf.append('\n'); 1215 long diff = now_ms - this.lastConnectionFailure; 1216 if (diff <= 0) { 1217 sbuf.append("lastConnectionFailure since <incorrect>"); 1218 } else { 1219 sbuf.append("lastConnectionFailure: ").append(Long.toString(diff/1000)); 1220 sbuf.append( "sec"); 1221 } 1222 } 1223 if (this.lastRoamingFailure != 0) { 1224 sbuf.append('\n'); 1225 long diff = now_ms - this.lastRoamingFailure; 1226 if (diff <= 0) { 1227 sbuf.append("lastRoamingFailure since <incorrect>"); 1228 } else { 1229 sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000)); 1230 sbuf.append( "sec"); 1231 } 1232 } 1233 sbuf.append("roamingFailureBlackListTimeMilli: "). 1234 append(Long.toString(this.roamingFailureBlackListTimeMilli)); 1235 sbuf.append('\n'); 1236 if (this.linkedConfigurations != null) { 1237 for(String key : this.linkedConfigurations.keySet()) { 1238 sbuf.append(" linked: ").append(key); 1239 sbuf.append('\n'); 1240 } 1241 } 1242 if (this.connectChoices != null) { 1243 for(String key : this.connectChoices.keySet()) { 1244 Integer choice = this.connectChoices.get(key); 1245 if (choice != null) { 1246 sbuf.append(" choice: ").append(key); 1247 sbuf.append(" = ").append(choice); 1248 sbuf.append('\n'); 1249 } 1250 } 1251 } 1252 if (this.scanResultCache != null) { 1253 sbuf.append("Scan Cache: ").append('\n'); 1254 ArrayList<ScanResult> list = sortScanResults(); 1255 if (list.size() > 0) { 1256 for (ScanResult result : list) { 1257 long milli = now_ms - result.seen; 1258 long ageSec = 0; 1259 long ageMin = 0; 1260 long ageHour = 0; 1261 long ageMilli = 0; 1262 long ageDay = 0; 1263 if (now_ms > result.seen && result.seen > 0) { 1264 ageMilli = milli % 1000; 1265 ageSec = (milli / 1000) % 60; 1266 ageMin = (milli / (60*1000)) % 60; 1267 ageHour = (milli / (60*60*1000)) % 24; 1268 ageDay = (milli / (24*60*60*1000)); 1269 } 1270 sbuf.append("{").append(result.BSSID).append(",").append(result.frequency); 1271 sbuf.append(",").append(String.format("%3d", result.level)); 1272 if (result.autoJoinStatus > 0) { 1273 sbuf.append(",st=").append(result.autoJoinStatus); 1274 } 1275 if (ageSec > 0 || ageMilli > 0) { 1276 sbuf.append(String.format(",%4d.%02d.%02d.%02d.%03dms", ageDay, 1277 ageHour, ageMin, ageSec, ageMilli)); 1278 } 1279 if (result.numIpConfigFailures > 0) { 1280 sbuf.append(",ipfail="); 1281 sbuf.append(result.numIpConfigFailures); 1282 } 1283 sbuf.append("} "); 1284 } 1285 sbuf.append('\n'); 1286 } 1287 } 1288 sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI); 1289 sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI); 1290 sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI); 1291 sbuf.append('\n'); 1292 sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI); 1293 sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI); 1294 sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI); 1295 sbuf.append('\n'); 1296 sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts); 1297 sbuf.append('\n'); 1298 sbuf.append("autoJoinBailedDueToLowRssi: ").append(this.autoJoinBailedDueToLowRssi); 1299 sbuf.append('\n'); 1300 sbuf.append("autoJoinUseAggressiveJoinAttemptThreshold: "); 1301 sbuf.append(this.autoJoinUseAggressiveJoinAttemptThreshold); 1302 sbuf.append('\n'); 1303 1304 return sbuf.toString(); 1305 } 1306 1307 /** 1308 * Construct a WifiConfiguration from a scanned network 1309 * @param scannedAP the scan result used to construct the config entry 1310 * TODO: figure out whether this is a useful way to construct a new entry. 1311 * 1312 public WifiConfiguration(ScanResult scannedAP) { 1313 networkId = -1; 1314 SSID = scannedAP.SSID; 1315 BSSID = scannedAP.BSSID; 1316 } 1317 */ 1318 1319 /** {@hide} */ 1320 public String getPrintableSsid() { 1321 if (SSID == null) return ""; 1322 final int length = SSID.length(); 1323 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 1324 return SSID.substring(1, length - 1); 1325 } 1326 1327 /** The ascii-encoded string format is P"<ascii-encoded-string>" 1328 * The decoding is implemented in the supplicant for a newly configured 1329 * network. 1330 */ 1331 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 1332 (SSID.charAt(length-1) == '"')) { 1333 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 1334 SSID.substring(2, length - 1)); 1335 return wifiSsid.toString(); 1336 } 1337 return SSID; 1338 } 1339 1340 /** 1341 * Get an identifier for associating credentials with this config 1342 * @param current configuration contains values for additional fields 1343 * that are not part of this configuration. Used 1344 * when a config with some fields is passed by an application. 1345 * @throws IllegalStateException if config is invalid for key id generation 1346 * @hide 1347 */ 1348 public String getKeyIdForCredentials(WifiConfiguration current) { 1349 String keyMgmt = null; 1350 1351 try { 1352 // Get current config details for fields that are not initialized 1353 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 1354 if (allowedKeyManagement.cardinality() == 0) { 1355 allowedKeyManagement = current.allowedKeyManagement; 1356 } 1357 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1358 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1359 } 1360 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1361 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 1362 } 1363 1364 if (TextUtils.isEmpty(keyMgmt)) { 1365 throw new IllegalStateException("Not an EAP network"); 1366 } 1367 1368 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 1369 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 1370 current.enterpriseConfig : null)); 1371 } catch (NullPointerException e) { 1372 throw new IllegalStateException("Invalid config details"); 1373 } 1374 } 1375 1376 private String trimStringForKeyId(String string) { 1377 // Remove quotes and spaces 1378 return string.replace("\"", "").replace(" ", ""); 1379 } 1380 1381 private static BitSet readBitSet(Parcel src) { 1382 int cardinality = src.readInt(); 1383 1384 BitSet set = new BitSet(); 1385 for (int i = 0; i < cardinality; i++) { 1386 set.set(src.readInt()); 1387 } 1388 1389 return set; 1390 } 1391 1392 private static void writeBitSet(Parcel dest, BitSet set) { 1393 int nextSetBit = -1; 1394 1395 dest.writeInt(set.cardinality()); 1396 1397 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1398 dest.writeInt(nextSetBit); 1399 } 1400 } 1401 1402 /** @hide */ 1403 public int getAuthType() { 1404 if (isValid() == false) { 1405 throw new IllegalStateException("Invalid configuration"); 1406 } 1407 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1408 return KeyMgmt.WPA_PSK; 1409 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 1410 return KeyMgmt.WPA2_PSK; 1411 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1412 return KeyMgmt.WPA_EAP; 1413 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1414 return KeyMgmt.IEEE8021X; 1415 } 1416 return KeyMgmt.NONE; 1417 } 1418 1419 /* @hide 1420 * Cache the config key, this seems useful as a speed up since a lot of 1421 * lookups in the config store are done and based on this key. 1422 */ 1423 String mCachedConfigKey; 1424 1425 /** @hide 1426 * return the string used to calculate the hash in WifiConfigStore 1427 * and uniquely identify this WifiConfiguration 1428 */ 1429 public String configKey(boolean allowCached) { 1430 String key; 1431 if (allowCached && mCachedConfigKey != null) { 1432 key = mCachedConfigKey; 1433 } else if (providerFriendlyName != null) { 1434 key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1435 } else { 1436 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1437 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1438 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1439 allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1440 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1441 } else if (wepKeys[0] != null) { 1442 key = SSID + "WEP"; 1443 } else { 1444 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1445 } 1446 mCachedConfigKey = key; 1447 } 1448 return key; 1449 } 1450 1451 /** @hide 1452 * get configKey, force calculating the config string 1453 */ 1454 public String configKey() { 1455 return configKey(false); 1456 } 1457 1458 /** @hide 1459 * return the config key string based on a scan result 1460 */ 1461 static public String configKey(ScanResult result) { 1462 String key = "\"" + result.SSID + "\""; 1463 1464 if (result.capabilities.contains("WEP")) { 1465 key = key + "-WEP"; 1466 } 1467 1468 if (result.capabilities.contains("PSK")) { 1469 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1470 } 1471 1472 if (result.capabilities.contains("EAP")) { 1473 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1474 } 1475 1476 return key; 1477 } 1478 1479 /** @hide */ 1480 public IpConfiguration getIpConfiguration() { 1481 return mIpConfiguration; 1482 } 1483 1484 /** @hide */ 1485 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1486 mIpConfiguration = ipConfiguration; 1487 } 1488 1489 /** @hide */ 1490 public StaticIpConfiguration getStaticIpConfiguration() { 1491 return mIpConfiguration.getStaticIpConfiguration(); 1492 } 1493 1494 /** @hide */ 1495 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 1496 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 1497 } 1498 1499 /** @hide */ 1500 public IpConfiguration.IpAssignment getIpAssignment() { 1501 return mIpConfiguration.ipAssignment; 1502 } 1503 1504 /** @hide */ 1505 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1506 mIpConfiguration.ipAssignment = ipAssignment; 1507 } 1508 1509 /** @hide */ 1510 public IpConfiguration.ProxySettings getProxySettings() { 1511 return mIpConfiguration.proxySettings; 1512 } 1513 1514 /** @hide */ 1515 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1516 mIpConfiguration.proxySettings = proxySettings; 1517 } 1518 1519 /** @hide */ 1520 public ProxyInfo getHttpProxy() { 1521 return mIpConfiguration.httpProxy; 1522 } 1523 1524 /** @hide */ 1525 public void setHttpProxy(ProxyInfo httpProxy) { 1526 mIpConfiguration.httpProxy = httpProxy; 1527 } 1528 1529 /** @hide */ 1530 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1531 mIpConfiguration.proxySettings = settings; 1532 mIpConfiguration.httpProxy = proxy; 1533 } 1534 1535 /** Implement the Parcelable interface {@hide} */ 1536 public int describeContents() { 1537 return 0; 1538 } 1539 1540 /** copy constructor {@hide} */ 1541 public WifiConfiguration(WifiConfiguration source) { 1542 if (source != null) { 1543 networkId = source.networkId; 1544 status = source.status; 1545 disableReason = source.disableReason; 1546 disableReason = source.disableReason; 1547 SSID = source.SSID; 1548 BSSID = source.BSSID; 1549 FQDN = source.FQDN; 1550 roamingConsortiumIds = new HashSet<Long>(); 1551 for (Long roamingConsortiumId : source.roamingConsortiumIds) { 1552 roamingConsortiumIds.add(roamingConsortiumId); 1553 } 1554 1555 providerFriendlyName = source.providerFriendlyName; 1556 preSharedKey = source.preSharedKey; 1557 1558 apBand = source.apBand; 1559 apChannel = source.apChannel; 1560 1561 wepKeys = new String[4]; 1562 for (int i = 0; i < wepKeys.length; i++) { 1563 wepKeys[i] = source.wepKeys[i]; 1564 } 1565 1566 wepTxKeyIndex = source.wepTxKeyIndex; 1567 priority = source.priority; 1568 hiddenSSID = source.hiddenSSID; 1569 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 1570 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 1571 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 1572 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 1573 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 1574 1575 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 1576 1577 defaultGwMacAddress = source.defaultGwMacAddress; 1578 1579 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 1580 1581 if ((source.scanResultCache != null) && (source.scanResultCache.size() > 0)) { 1582 scanResultCache = new HashMap<String, ScanResult>(); 1583 scanResultCache.putAll(source.scanResultCache); 1584 } 1585 1586 if ((source.connectChoices != null) && (source.connectChoices.size() > 0)) { 1587 connectChoices = new HashMap<String, Integer>(); 1588 connectChoices.putAll(source.connectChoices); 1589 } 1590 1591 if ((source.linkedConfigurations != null) 1592 && (source.linkedConfigurations.size() > 0)) { 1593 linkedConfigurations = new HashMap<String, Integer>(); 1594 linkedConfigurations.putAll(source.linkedConfigurations); 1595 } 1596 mCachedConfigKey = null; //force null configKey 1597 autoJoinStatus = source.autoJoinStatus; 1598 selfAdded = source.selfAdded; 1599 validatedInternetAccess = source.validatedInternetAccess; 1600 ephemeral = source.ephemeral; 1601 if (source.visibility != null) { 1602 visibility = new Visibility(source.visibility); 1603 } 1604 1605 lastFailure = source.lastFailure; 1606 didSelfAdd = source.didSelfAdd; 1607 lastConnectUid = source.lastConnectUid; 1608 lastUpdateUid = source.lastUpdateUid; 1609 creatorUid = source.creatorUid; 1610 peerWifiConfiguration = source.peerWifiConfiguration; 1611 blackListTimestamp = source.blackListTimestamp; 1612 lastConnected = source.lastConnected; 1613 lastDisconnected = source.lastDisconnected; 1614 lastConnectionFailure = source.lastConnectionFailure; 1615 lastRoamingFailure = source.lastRoamingFailure; 1616 lastRoamingFailureReason = source.lastRoamingFailureReason; 1617 roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli; 1618 numConnectionFailures = source.numConnectionFailures; 1619 numIpConfigFailures = source.numIpConfigFailures; 1620 numAuthFailures = source.numAuthFailures; 1621 numScorerOverride = source.numScorerOverride; 1622 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 1623 numAssociation = source.numAssociation; 1624 numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI; 1625 numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI; 1626 numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI; 1627 numTicksAtLowRSSI = source.numTicksAtLowRSSI; 1628 numTicksAtBadRSSI = source.numTicksAtBadRSSI; 1629 numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI; 1630 numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts; 1631 autoJoinBSSID = source.autoJoinBSSID; 1632 autoJoinUseAggressiveJoinAttemptThreshold 1633 = source.autoJoinUseAggressiveJoinAttemptThreshold; 1634 autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi; 1635 dirty = source.dirty; 1636 numNoInternetAccessReports = source.numNoInternetAccessReports; 1637 } 1638 } 1639 1640 /** {@hide} */ 1641 //public static final int NOTHING_TAG = 0; 1642 /** {@hide} */ 1643 //public static final int SCAN_CACHE_TAG = 1; 1644 1645 /** Implement the Parcelable interface {@hide} */ 1646 @Override 1647 public void writeToParcel(Parcel dest, int flags) { 1648 dest.writeInt(networkId); 1649 dest.writeInt(status); 1650 dest.writeInt(disableReason); 1651 dest.writeString(SSID); 1652 dest.writeString(BSSID); 1653 dest.writeInt(apBand); 1654 dest.writeInt(apChannel); 1655 dest.writeString(autoJoinBSSID); 1656 dest.writeString(FQDN); 1657 dest.writeString(providerFriendlyName); 1658 dest.writeInt(roamingConsortiumIds.size()); 1659 for (Long roamingConsortiumId : roamingConsortiumIds) { 1660 dest.writeLong(roamingConsortiumId); 1661 } 1662 dest.writeString(preSharedKey); 1663 for (String wepKey : wepKeys) { 1664 dest.writeString(wepKey); 1665 } 1666 dest.writeInt(wepTxKeyIndex); 1667 dest.writeInt(priority); 1668 dest.writeInt(hiddenSSID ? 1 : 0); 1669 dest.writeInt(requirePMF ? 1 : 0); 1670 dest.writeString(updateIdentifier); 1671 1672 writeBitSet(dest, allowedKeyManagement); 1673 writeBitSet(dest, allowedProtocols); 1674 writeBitSet(dest, allowedAuthAlgorithms); 1675 writeBitSet(dest, allowedPairwiseCiphers); 1676 writeBitSet(dest, allowedGroupCiphers); 1677 1678 dest.writeParcelable(enterpriseConfig, flags); 1679 1680 dest.writeParcelable(mIpConfiguration, flags); 1681 dest.writeString(dhcpServer); 1682 dest.writeString(defaultGwMacAddress); 1683 dest.writeInt(autoJoinStatus); 1684 dest.writeInt(selfAdded ? 1 : 0); 1685 dest.writeInt(didSelfAdd ? 1 : 0); 1686 dest.writeInt(validatedInternetAccess ? 1 : 0); 1687 dest.writeInt(ephemeral ? 1 : 0); 1688 dest.writeInt(creatorUid); 1689 dest.writeInt(lastConnectUid); 1690 dest.writeInt(lastUpdateUid); 1691 dest.writeLong(blackListTimestamp); 1692 dest.writeLong(lastConnectionFailure); 1693 dest.writeLong(lastRoamingFailure); 1694 dest.writeInt(lastRoamingFailureReason); 1695 dest.writeLong(roamingFailureBlackListTimeMilli); 1696 dest.writeInt(numConnectionFailures); 1697 dest.writeInt(numIpConfigFailures); 1698 dest.writeInt(numAuthFailures); 1699 dest.writeInt(numScorerOverride); 1700 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 1701 dest.writeInt(numAssociation); 1702 dest.writeInt(numUserTriggeredWifiDisableLowRSSI); 1703 dest.writeInt(numUserTriggeredWifiDisableBadRSSI); 1704 dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI); 1705 dest.writeInt(numTicksAtLowRSSI); 1706 dest.writeInt(numTicksAtBadRSSI); 1707 dest.writeInt(numTicksAtNotHighRSSI); 1708 dest.writeInt(numUserTriggeredJoinAttempts); 1709 dest.writeInt(autoJoinUseAggressiveJoinAttemptThreshold); 1710 dest.writeInt(autoJoinBailedDueToLowRssi ? 1 : 0); 1711 dest.writeInt(numNoInternetAccessReports); 1712 } 1713 1714 /** Implement the Parcelable interface {@hide} */ 1715 public static final Creator<WifiConfiguration> CREATOR = 1716 new Creator<WifiConfiguration>() { 1717 public WifiConfiguration createFromParcel(Parcel in) { 1718 WifiConfiguration config = new WifiConfiguration(); 1719 config.networkId = in.readInt(); 1720 config.status = in.readInt(); 1721 config.disableReason = in.readInt(); 1722 config.SSID = in.readString(); 1723 config.BSSID = in.readString(); 1724 config.apBand = in.readInt(); 1725 config.apChannel = in.readInt(); 1726 config.autoJoinBSSID = in.readString(); 1727 config.FQDN = in.readString(); 1728 config.providerFriendlyName = in.readString(); 1729 int numRoamingConsortiumIds = in.readInt(); 1730 for (int i = 0; i < numRoamingConsortiumIds; i++) { 1731 config.roamingConsortiumIds.add(in.readLong()); 1732 } 1733 config.preSharedKey = in.readString(); 1734 for (int i = 0; i < config.wepKeys.length; i++) { 1735 config.wepKeys[i] = in.readString(); 1736 } 1737 config.wepTxKeyIndex = in.readInt(); 1738 config.priority = in.readInt(); 1739 config.hiddenSSID = in.readInt() != 0; 1740 config.requirePMF = in.readInt() != 0; 1741 config.updateIdentifier = in.readString(); 1742 1743 config.allowedKeyManagement = readBitSet(in); 1744 config.allowedProtocols = readBitSet(in); 1745 config.allowedAuthAlgorithms = readBitSet(in); 1746 config.allowedPairwiseCiphers = readBitSet(in); 1747 config.allowedGroupCiphers = readBitSet(in); 1748 1749 config.enterpriseConfig = in.readParcelable(null); 1750 1751 config.mIpConfiguration = in.readParcelable(null); 1752 config.dhcpServer = in.readString(); 1753 config.defaultGwMacAddress = in.readString(); 1754 config.autoJoinStatus = in.readInt(); 1755 config.selfAdded = in.readInt() != 0; 1756 config.didSelfAdd = in.readInt() != 0; 1757 config.validatedInternetAccess = in.readInt() != 0; 1758 config.ephemeral = in.readInt() != 0; 1759 config.creatorUid = in.readInt(); 1760 config.lastConnectUid = in.readInt(); 1761 config.lastUpdateUid = in.readInt(); 1762 config.blackListTimestamp = in.readLong(); 1763 config.lastConnectionFailure = in.readLong(); 1764 config.lastRoamingFailure = in.readLong(); 1765 config.lastRoamingFailureReason = in.readInt(); 1766 config.roamingFailureBlackListTimeMilli = in.readLong(); 1767 config.numConnectionFailures = in.readInt(); 1768 config.numIpConfigFailures = in.readInt(); 1769 config.numAuthFailures = in.readInt(); 1770 config.numScorerOverride = in.readInt(); 1771 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 1772 config.numAssociation = in.readInt(); 1773 config.numUserTriggeredWifiDisableLowRSSI = in.readInt(); 1774 config.numUserTriggeredWifiDisableBadRSSI = in.readInt(); 1775 config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt(); 1776 config.numTicksAtLowRSSI = in.readInt(); 1777 config.numTicksAtBadRSSI = in.readInt(); 1778 config.numTicksAtNotHighRSSI = in.readInt(); 1779 config.numUserTriggeredJoinAttempts = in.readInt(); 1780 config.autoJoinUseAggressiveJoinAttemptThreshold = in.readInt(); 1781 config.autoJoinBailedDueToLowRssi = in.readInt() != 0; 1782 config.numNoInternetAccessReports = in.readInt(); 1783 return config; 1784 } 1785 1786 public WifiConfiguration[] newArray(int size) { 1787 return new WifiConfiguration[size]; 1788 } 1789 }; 1790} 1791