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 validated internet access 356 */ 357 public boolean validatedInternetAccess; 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 public int score; // Debug only, indicate last score used for autojoin/cell-handover 491 public int currentNetworkBoost; // Debug only, indicate boost applied to RSSI if current 492 public int bandPreferenceBoost; // Debug only, indicate boost applied to RSSI if current 493 public int lastChoiceBoost; // Debug only, indicate last choice applied to this configuration 494 public String lastChoiceConfig; // Debug only, indicate last choice applied to this configuration 495 496 public Visibility() { 497 rssi5 = INVALID_RSSI; 498 rssi24 = INVALID_RSSI; 499 } 500 501 public Visibility(Visibility source) { 502 rssi5 = source.rssi5; 503 rssi24 = source.rssi24; 504 age24 = source.age24; 505 age5 = source.age5; 506 num24 = source.num24; 507 num5 = source.num5; 508 BSSID5 = source.BSSID5; 509 BSSID24 = source.BSSID24; 510 } 511 512 @Override 513 public String toString() { 514 StringBuilder sbuf = new StringBuilder(); 515 sbuf.append("["); 516 if (rssi24 > INVALID_RSSI) { 517 sbuf.append(Integer.toString(rssi24)); 518 sbuf.append(","); 519 sbuf.append(Integer.toString(num24)); 520 if (BSSID24 != null) sbuf.append(",").append(BSSID24); 521 } 522 sbuf.append("; "); 523 if (rssi5 > INVALID_RSSI) { 524 sbuf.append(Integer.toString(rssi5)); 525 sbuf.append(","); 526 sbuf.append(Integer.toString(num5)); 527 if (BSSID5 != null) sbuf.append(",").append(BSSID5); 528 } 529 if (score != 0) { 530 sbuf.append("; ").append(score); 531 sbuf.append(", ").append(currentNetworkBoost); 532 sbuf.append(", ").append(bandPreferenceBoost); 533 if (lastChoiceConfig != null) { 534 sbuf.append(", ").append(lastChoiceBoost); 535 sbuf.append(", ").append(lastChoiceConfig); 536 } 537 } 538 sbuf.append("]"); 539 return sbuf.toString(); 540 } 541 } 542 543 /** @hide 544 * Cache the visibility status of this configuration. 545 * Visibility can change at any time depending on scan results availability. 546 * Owner of the WifiConfiguration is responsible to set this field based on 547 * recent scan results. 548 ***/ 549 public Visibility visibility; 550 551 /** @hide 552 * calculate and set Visibility for that configuration. 553 * 554 * age in milliseconds: we will consider only ScanResults that are more recent, 555 * i.e. younger. 556 ***/ 557 public Visibility setVisibility(long age) { 558 if (scanResultCache == null) { 559 visibility = null; 560 return null; 561 } 562 563 Visibility status = new Visibility(); 564 565 long now_ms = System.currentTimeMillis(); 566 for(ScanResult result : scanResultCache.values()) { 567 if (result.seen == 0) 568 continue; 569 570 if (result.is5GHz()) { 571 //strictly speaking: [4915, 5825] 572 //number of known BSSID on 5GHz band 573 status.num5 = status.num5 + 1; 574 } else if (result.is24GHz()) { 575 //strictly speaking: [2412, 2482] 576 //number of known BSSID on 2.4Ghz band 577 status.num24 = status.num24 + 1; 578 } 579 580 if ((now_ms - result.seen) > age) continue; 581 582 if (result.is5GHz()) { 583 if (result.level > status.rssi5) { 584 status.rssi5 = result.level; 585 status.age5 = result.seen; 586 status.BSSID5 = result.BSSID; 587 } 588 } else if (result.is24GHz()) { 589 if (result.level > status.rssi24) { 590 status.rssi24 = result.level; 591 status.age24 = result.seen; 592 status.BSSID24 = result.BSSID; 593 } 594 } 595 } 596 visibility = status; 597 return status; 598 } 599 600 /** @hide */ 601 public static final int AUTO_JOIN_ENABLED = 0; 602 /** 603 * if this is set, the WifiConfiguration cannot use linkages so as to bump 604 * it's relative priority. 605 * - status between and 128 indicate various level of blacklisting depending 606 * on the severity or frequency of the connection error 607 * - deleted status indicates that the user is deleting the configuration, and so 608 * although it may have been self added we will not re-self-add it, ignore it, 609 * not return it to applications, and not connect to it 610 * */ 611 612 /** @hide 613 * network was temporary disabled due to bad connection, most likely due 614 * to weak RSSI */ 615 public static final int AUTO_JOIN_TEMPORARY_DISABLED = 1; 616 /** @hide 617 * network was temporary disabled due to bad connection, which cant be attributed 618 * to weak RSSI */ 619 public static final int AUTO_JOIN_TEMPORARY_DISABLED_LINK_ERRORS = 32; 620 /** @hide */ 621 public static final int AUTO_JOIN_TEMPORARY_DISABLED_AT_SUPPLICANT = 64; 622 /** @hide */ 623 public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE = 128; 624 /** @hide */ 625 public static final int AUTO_JOIN_DISABLED_NO_CREDENTIALS = 160; 626 /** @hide */ 627 public static final int AUTO_JOIN_DISABLED_USER_ACTION = 161; 628 629 /** @hide */ 630 public static final int AUTO_JOIN_DELETED = 200; 631 632 /** 633 * @hide 634 */ 635 public int autoJoinStatus; 636 637 /** 638 * @hide 639 * Number of connection failures 640 */ 641 public int numConnectionFailures; 642 643 /** 644 * @hide 645 * Number of IP config failures 646 */ 647 public int numIpConfigFailures; 648 649 /** 650 * @hide 651 * Number of Auth failures 652 */ 653 public int numAuthFailures; 654 655 /** 656 * @hide 657 * Number of reports indicating no Internet Access 658 */ 659 public int numNoInternetAccessReports; 660 661 /** 662 * @hide 663 * The WiFi configuration is considered to have no internet access for purpose of autojoining 664 * if there has been a report of it having no internet access, and, it never have had 665 * internet access in the past. 666 */ 667 public boolean hasNoInternetAccess() { 668 return numNoInternetAccessReports > 0 && !validatedInternetAccess; 669 } 670 671 /** 672 * @hide 673 * Last time we blacklisted the configuration 674 */ 675 public long blackListTimestamp; 676 677 /** 678 * @hide 679 * Last time the system was connected to this configuration. 680 */ 681 public long lastConnected; 682 683 /** 684 * @hide 685 * Last time the system tried to connect and failed. 686 */ 687 public long lastConnectionFailure; 688 689 /** 690 * @hide 691 * Last time the system tried to roam and failed because of authentication failure or DHCP 692 * RENEW failure. 693 */ 694 public long lastRoamingFailure; 695 696 /** @hide */ 697 public static int ROAMING_FAILURE_IP_CONFIG = 1; 698 /** @hide */ 699 public static int ROAMING_FAILURE_AUTH_FAILURE = 2; 700 701 /** 702 * @hide 703 * Initial amount of time this Wifi configuration gets blacklisted for network switching 704 * because of roaming failure 705 */ 706 public long roamingFailureBlackListTimeMilli = 1000; 707 708 /** 709 * @hide 710 * Last roaming failure reason code 711 */ 712 public int lastRoamingFailureReason; 713 714 /** 715 * @hide 716 * Last time the system was disconnected to this configuration. 717 */ 718 public long lastDisconnected; 719 720 /** 721 * Set if the configuration was self added by the framework 722 * This boolean is cleared if we get a connect/save/ update or 723 * any wifiManager command that indicate the user interacted with the configuration 724 * since we will now consider that the configuration belong to him. 725 * @hide 726 */ 727 public boolean selfAdded; 728 729 /** 730 * Set if the configuration was self added by the framework 731 * This boolean is set once and never cleared. It is used 732 * so as we never loose track of who created the 733 * configuration in the first place. 734 * @hide 735 */ 736 public boolean didSelfAdd; 737 738 /** 739 * Peer WifiConfiguration this WifiConfiguration was added for 740 * @hide 741 */ 742 public String peerWifiConfiguration; 743 744 /** 745 * @hide 746 * Indicate that a WifiConfiguration is temporary and should not be saved 747 * nor considered by AutoJoin. 748 */ 749 public boolean ephemeral; 750 751 /** 752 * @hide 753 * Indicate that we didn't auto-join because rssi was too low 754 */ 755 public boolean autoJoinBailedDueToLowRssi; 756 757 /** 758 * @hide 759 * AutoJoin even though RSSI is 10dB below threshold 760 */ 761 public int autoJoinUseAggressiveJoinAttemptThreshold; 762 763 /** 764 * @hide 765 * Number of time the scorer overrode a the priority based choice, when comparing two 766 * WifiConfigurations, note that since comparing WifiConfiguration happens very often 767 * potentially at every scan, this number might become very large, even on an idle 768 * system. 769 */ 770 @SystemApi 771 public int numScorerOverride; 772 773 /** 774 * @hide 775 * Number of time the scorer overrode a the priority based choice, and the comparison 776 * triggered a network switch 777 */ 778 @SystemApi 779 public int numScorerOverrideAndSwitchedNetwork; 780 781 /** 782 * @hide 783 * Number of time we associated to this configuration. 784 */ 785 @SystemApi 786 public int numAssociation; 787 788 /** 789 * @hide 790 * Number of time user disabled WiFi while associated to this configuration with Low RSSI. 791 */ 792 public int numUserTriggeredWifiDisableLowRSSI; 793 794 /** 795 * @hide 796 * Number of time user disabled WiFi while associated to this configuration with Bad RSSI. 797 */ 798 public int numUserTriggeredWifiDisableBadRSSI; 799 800 /** 801 * @hide 802 * Number of time user disabled WiFi while associated to this configuration 803 * and RSSI was not HIGH. 804 */ 805 public int numUserTriggeredWifiDisableNotHighRSSI; 806 807 /** 808 * @hide 809 * Number of ticks associated to this configuration with Low RSSI. 810 */ 811 public int numTicksAtLowRSSI; 812 813 /** 814 * @hide 815 * Number of ticks associated to this configuration with Bad RSSI. 816 */ 817 public int numTicksAtBadRSSI; 818 819 /** 820 * @hide 821 * Number of ticks associated to this configuration 822 * and RSSI was not HIGH. 823 */ 824 public int numTicksAtNotHighRSSI; 825 /** 826 * @hide 827 * Number of time user (WifiManager) triggered association to this configuration. 828 * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps 829 */ 830 public int numUserTriggeredJoinAttempts; 831 832 /** 833 * @hide 834 * Connect choices 835 * 836 * remember the keys identifying the known WifiConfiguration over which this configuration 837 * was preferred by user or a "WiFi Network Management app", that is, 838 * a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration 839 * was visible to the user: 840 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 841 * 842 * The integer represents the configuration's RSSI at that time (useful?) 843 * 844 * The overall auto-join algorithm make use of past connect choice so as to sort configuration, 845 * the exact algorithm still fluctuating as of 5/7/2014 846 * 847 */ 848 public HashMap<String, Integer> connectChoices; 849 850 /** 851 * @hide 852 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 853 * regarding roaming and auto-joining. 854 * The linked configuration may or may not have same SSID, and may or may not have same 855 * credentials. 856 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 857 */ 858 public HashMap<String, Integer> linkedConfigurations; 859 860 public WifiConfiguration() { 861 networkId = INVALID_NETWORK_ID; 862 SSID = null; 863 BSSID = null; 864 FQDN = null; 865 naiRealm = null; 866 priority = 0; 867 hiddenSSID = false; 868 disableReason = DISABLED_UNKNOWN_REASON; 869 allowedKeyManagement = new BitSet(); 870 allowedProtocols = new BitSet(); 871 allowedAuthAlgorithms = new BitSet(); 872 allowedPairwiseCiphers = new BitSet(); 873 allowedGroupCiphers = new BitSet(); 874 wepKeys = new String[4]; 875 for (int i = 0; i < wepKeys.length; i++) { 876 wepKeys[i] = null; 877 } 878 enterpriseConfig = new WifiEnterpriseConfig(); 879 autoJoinStatus = AUTO_JOIN_ENABLED; 880 selfAdded = false; 881 didSelfAdd = false; 882 ephemeral = false; 883 validatedInternetAccess = false; 884 mIpConfiguration = new IpConfiguration(); 885 } 886 887 /** 888 * indicates whether the configuration is valid 889 * @return true if valid, false otherwise 890 * @hide 891 */ 892 public boolean isValid() { 893 894 if (allowedKeyManagement == null) 895 return false; 896 897 if (allowedKeyManagement.cardinality() > 1) { 898 if (allowedKeyManagement.cardinality() != 2) { 899 return false; 900 } 901 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) { 902 return false; 903 } 904 if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false) 905 && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) { 906 return false; 907 } 908 } 909 910 // TODO: Add more checks 911 return true; 912 } 913 914 /** 915 * Helper function, identify if a configuration is linked 916 * @hide 917 */ 918 public boolean isLinked(WifiConfiguration config) { 919 if (config.linkedConfigurations != null && linkedConfigurations != null) { 920 if (config.linkedConfigurations.get(configKey()) != null 921 && linkedConfigurations.get(config.configKey()) != null) { 922 return true; 923 } 924 } 925 return false; 926 } 927 928 /** 929 * most recent time we have seen this configuration 930 * @return most recent scanResult 931 * @hide 932 */ 933 public ScanResult lastSeen() { 934 ScanResult mostRecent = null; 935 936 if (scanResultCache == null) { 937 return null; 938 } 939 940 for (ScanResult result : scanResultCache.values()) { 941 if (mostRecent == null) { 942 if (result.seen != 0) 943 mostRecent = result; 944 } else { 945 if (result.seen > mostRecent.seen) { 946 mostRecent = result; 947 } 948 } 949 } 950 return mostRecent; 951 } 952 953 /** @hide **/ 954 public void setAutoJoinStatus(int status) { 955 if (status < 0) status = 0; 956 if (status == 0) { 957 blackListTimestamp = 0; 958 } else if (status > autoJoinStatus) { 959 blackListTimestamp = System.currentTimeMillis(); 960 } 961 if (status != autoJoinStatus) { 962 autoJoinStatus = status; 963 dirty = true; 964 } 965 } 966 967 /** @hide 968 * trim the scan Result Cache 969 * @param: number of entries to keep in the cache 970 */ 971 public void trimScanResultsCache(int num) { 972 if (this.scanResultCache == null) { 973 return; 974 } 975 int currenSize = this.scanResultCache.size(); 976 if (currenSize <= num) { 977 return; // Nothing to trim 978 } 979 ArrayList<ScanResult> list = new ArrayList<ScanResult>(this.scanResultCache.values()); 980 if (list.size() != 0) { 981 // Sort by descending timestamp 982 Collections.sort(list, new Comparator() { 983 public int compare(Object o1, Object o2) { 984 ScanResult a = (ScanResult)o1; 985 ScanResult b = (ScanResult)o2; 986 if (a.seen > b.seen) { 987 return 1; 988 } 989 if (a.seen < b.seen) { 990 return -1; 991 } 992 return a.BSSID.compareTo(b.BSSID); 993 } 994 }); 995 } 996 for (int i = 0; i < currenSize - num ; i++) { 997 // Remove oldest results from scan cache 998 ScanResult result = list.get(i); 999 this.scanResultCache.remove(result.BSSID); 1000 } 1001 } 1002 1003 /* @hide */ 1004 private ArrayList<ScanResult> sortScanResults() { 1005 ArrayList<ScanResult> list = new ArrayList<ScanResult>(this.scanResultCache.values()); 1006 if (list.size() != 0) { 1007 Collections.sort(list, new Comparator() { 1008 public int compare(Object o1, Object o2) { 1009 ScanResult a = (ScanResult)o1; 1010 ScanResult b = (ScanResult)o2; 1011 if (a.numIpConfigFailures > b.numIpConfigFailures) { 1012 return 1; 1013 } 1014 if (a.numIpConfigFailures < b.numIpConfigFailures) { 1015 return -1; 1016 } 1017 if (a.seen > b.seen) { 1018 return -1; 1019 } 1020 if (a.seen < b.seen) { 1021 return 1; 1022 } 1023 if (a.level > b.level) { 1024 return -1; 1025 } 1026 if (a.level < b.level) { 1027 return 1; 1028 } 1029 return a.BSSID.compareTo(b.BSSID); 1030 } 1031 }); 1032 } 1033 return list; 1034 } 1035 1036 @Override 1037 public String toString() { 1038 StringBuilder sbuf = new StringBuilder(); 1039 if (this.status == WifiConfiguration.Status.CURRENT) { 1040 sbuf.append("* "); 1041 } else if (this.status == WifiConfiguration.Status.DISABLED) { 1042 sbuf.append("- DSBLE "); 1043 } 1044 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 1045 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN). 1046 append(" REALM: ").append(this.naiRealm).append(" PRIO: ").append(this.priority). 1047 append('\n'); 1048 if (this.numConnectionFailures > 0) { 1049 sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n"); 1050 } 1051 if (this.numIpConfigFailures > 0) { 1052 sbuf.append(" numIpConfigFailures ").append(this.numIpConfigFailures).append("\n"); 1053 } 1054 if (this.numAuthFailures > 0) { 1055 sbuf.append(" numAuthFailures ").append(this.numAuthFailures).append("\n"); 1056 } 1057 if (this.autoJoinStatus > 0) { 1058 sbuf.append(" autoJoinStatus ").append(this.autoJoinStatus).append("\n"); 1059 } 1060 if (this.disableReason > 0) { 1061 sbuf.append(" disableReason ").append(this.disableReason).append("\n"); 1062 } 1063 if (this.numAssociation > 0) { 1064 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 1065 } 1066 if (this.numNoInternetAccessReports > 0) { 1067 sbuf.append(" numNoInternetAccessReports "); 1068 sbuf.append(this.numNoInternetAccessReports).append("\n"); 1069 } 1070 if (this.didSelfAdd) sbuf.append(" didSelfAdd"); 1071 if (this.selfAdded) sbuf.append(" selfAdded"); 1072 if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); 1073 if (this.ephemeral) sbuf.append(" ephemeral"); 1074 if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess || this.ephemeral) { 1075 sbuf.append("\n"); 1076 } 1077 sbuf.append(" KeyMgmt:"); 1078 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 1079 if (this.allowedKeyManagement.get(k)) { 1080 sbuf.append(" "); 1081 if (k < KeyMgmt.strings.length) { 1082 sbuf.append(KeyMgmt.strings[k]); 1083 } else { 1084 sbuf.append("??"); 1085 } 1086 } 1087 } 1088 sbuf.append(" Protocols:"); 1089 for (int p = 0; p < this.allowedProtocols.size(); p++) { 1090 if (this.allowedProtocols.get(p)) { 1091 sbuf.append(" "); 1092 if (p < Protocol.strings.length) { 1093 sbuf.append(Protocol.strings[p]); 1094 } else { 1095 sbuf.append("??"); 1096 } 1097 } 1098 } 1099 sbuf.append('\n'); 1100 sbuf.append(" AuthAlgorithms:"); 1101 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 1102 if (this.allowedAuthAlgorithms.get(a)) { 1103 sbuf.append(" "); 1104 if (a < AuthAlgorithm.strings.length) { 1105 sbuf.append(AuthAlgorithm.strings[a]); 1106 } else { 1107 sbuf.append("??"); 1108 } 1109 } 1110 } 1111 sbuf.append('\n'); 1112 sbuf.append(" PairwiseCiphers:"); 1113 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 1114 if (this.allowedPairwiseCiphers.get(pc)) { 1115 sbuf.append(" "); 1116 if (pc < PairwiseCipher.strings.length) { 1117 sbuf.append(PairwiseCipher.strings[pc]); 1118 } else { 1119 sbuf.append("??"); 1120 } 1121 } 1122 } 1123 sbuf.append('\n'); 1124 sbuf.append(" GroupCiphers:"); 1125 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 1126 if (this.allowedGroupCiphers.get(gc)) { 1127 sbuf.append(" "); 1128 if (gc < GroupCipher.strings.length) { 1129 sbuf.append(GroupCipher.strings[gc]); 1130 } else { 1131 sbuf.append("??"); 1132 } 1133 } 1134 } 1135 sbuf.append('\n').append(" PSK: "); 1136 if (this.preSharedKey != null) { 1137 sbuf.append('*'); 1138 } 1139 sbuf.append("\nEnterprise config:\n"); 1140 sbuf.append(enterpriseConfig); 1141 1142 sbuf.append("IP config:\n"); 1143 sbuf.append(mIpConfiguration.toString()); 1144 1145 if (this.creatorUid != 0) sbuf.append(" uid=" + Integer.toString(creatorUid)); 1146 if (this.autoJoinBSSID != null) sbuf.append(" autoJoinBSSID=" + autoJoinBSSID); 1147 long now_ms = System.currentTimeMillis(); 1148 if (this.blackListTimestamp != 0) { 1149 sbuf.append('\n'); 1150 long diff = now_ms - this.blackListTimestamp; 1151 if (diff <= 0) { 1152 sbuf.append(" blackListed since <incorrect>"); 1153 } else { 1154 sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec"); 1155 } 1156 } 1157 if (this.lastConnected != 0) { 1158 sbuf.append('\n'); 1159 long diff = now_ms - this.lastConnected; 1160 if (diff <= 0) { 1161 sbuf.append("lastConnected since <incorrect>"); 1162 } else { 1163 sbuf.append("lastConnected: ").append(Long.toString(diff/1000)).append( "sec"); 1164 } 1165 } 1166 if (this.lastConnectionFailure != 0) { 1167 sbuf.append('\n'); 1168 long diff = now_ms - this.lastConnectionFailure; 1169 if (diff <= 0) { 1170 sbuf.append("lastConnectionFailure since <incorrect>"); 1171 } else { 1172 sbuf.append("lastConnectionFailure: ").append(Long.toString(diff/1000)); 1173 sbuf.append( "sec"); 1174 } 1175 } 1176 if (this.lastRoamingFailure != 0) { 1177 sbuf.append('\n'); 1178 long diff = now_ms - this.lastRoamingFailure; 1179 if (diff <= 0) { 1180 sbuf.append("lastRoamingFailure since <incorrect>"); 1181 } else { 1182 sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000)); 1183 sbuf.append( "sec"); 1184 } 1185 } 1186 sbuf.append("roamingFailureBlackListTimeMilli: "). 1187 append(Long.toString(this.roamingFailureBlackListTimeMilli)); 1188 sbuf.append('\n'); 1189 if (this.linkedConfigurations != null) { 1190 for(String key : this.linkedConfigurations.keySet()) { 1191 sbuf.append(" linked: ").append(key); 1192 sbuf.append('\n'); 1193 } 1194 } 1195 if (this.connectChoices != null) { 1196 for(String key : this.connectChoices.keySet()) { 1197 Integer choice = this.connectChoices.get(key); 1198 if (choice != null) { 1199 sbuf.append(" choice: ").append(key); 1200 sbuf.append(" = ").append(choice); 1201 sbuf.append('\n'); 1202 } 1203 } 1204 } 1205 if (this.scanResultCache != null) { 1206 sbuf.append("Scan Cache: ").append('\n'); 1207 ArrayList<ScanResult> list = sortScanResults(); 1208 if (list.size() > 0) { 1209 for (ScanResult result : list) { 1210 long milli = now_ms - result.seen; 1211 long ageSec = 0; 1212 long ageMin = 0; 1213 long ageHour = 0; 1214 long ageMilli = 0; 1215 long ageDay = 0; 1216 if (now_ms > result.seen && result.seen > 0) { 1217 ageMilli = milli % 1000; 1218 ageSec = (milli / 1000) % 60; 1219 ageMin = (milli / (60*1000)) % 60; 1220 ageHour = (milli / (60*60*1000)) % 24; 1221 ageDay = (milli / (24*60*60*1000)); 1222 } 1223 sbuf.append("{").append(result.BSSID).append(",").append(result.frequency); 1224 sbuf.append(",").append(String.format("%3d", result.level)); 1225 if (result.autoJoinStatus > 0) { 1226 sbuf.append(",st=").append(result.autoJoinStatus); 1227 } 1228 if (ageSec > 0 || ageMilli > 0) { 1229 sbuf.append(String.format(",%4d.%02d.%02d.%02d.%03dms", ageDay, 1230 ageHour, ageMin, ageSec, ageMilli)); 1231 } 1232 if (result.numIpConfigFailures > 0) { 1233 sbuf.append(",ipfail="); 1234 sbuf.append(result.numIpConfigFailures); 1235 } 1236 sbuf.append("} "); 1237 } 1238 sbuf.append('\n'); 1239 } 1240 } 1241 sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI); 1242 sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI); 1243 sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI); 1244 sbuf.append('\n'); 1245 sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI); 1246 sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI); 1247 sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI); 1248 sbuf.append('\n'); 1249 sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts); 1250 sbuf.append('\n'); 1251 sbuf.append("autoJoinBailedDueToLowRssi: ").append(this.autoJoinBailedDueToLowRssi); 1252 sbuf.append('\n'); 1253 sbuf.append("autoJoinUseAggressiveJoinAttemptThreshold: "); 1254 sbuf.append(this.autoJoinUseAggressiveJoinAttemptThreshold); 1255 sbuf.append('\n'); 1256 1257 return sbuf.toString(); 1258 } 1259 1260 /** 1261 * Construct a WifiConfiguration from a scanned network 1262 * @param scannedAP the scan result used to construct the config entry 1263 * TODO: figure out whether this is a useful way to construct a new entry. 1264 * 1265 public WifiConfiguration(ScanResult scannedAP) { 1266 networkId = -1; 1267 SSID = scannedAP.SSID; 1268 BSSID = scannedAP.BSSID; 1269 } 1270 */ 1271 1272 /** {@hide} */ 1273 public String getPrintableSsid() { 1274 if (SSID == null) return ""; 1275 final int length = SSID.length(); 1276 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 1277 return SSID.substring(1, length - 1); 1278 } 1279 1280 /** The ascii-encoded string format is P"<ascii-encoded-string>" 1281 * The decoding is implemented in the supplicant for a newly configured 1282 * network. 1283 */ 1284 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 1285 (SSID.charAt(length-1) == '"')) { 1286 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 1287 SSID.substring(2, length - 1)); 1288 return wifiSsid.toString(); 1289 } 1290 return SSID; 1291 } 1292 1293 /** 1294 * Get an identifier for associating credentials with this config 1295 * @param current configuration contains values for additional fields 1296 * that are not part of this configuration. Used 1297 * when a config with some fields is passed by an application. 1298 * @throws IllegalStateException if config is invalid for key id generation 1299 * @hide 1300 */ 1301 public String getKeyIdForCredentials(WifiConfiguration current) { 1302 String keyMgmt = null; 1303 1304 try { 1305 // Get current config details for fields that are not initialized 1306 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 1307 if (allowedKeyManagement.cardinality() == 0) { 1308 allowedKeyManagement = current.allowedKeyManagement; 1309 } 1310 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1311 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1312 } 1313 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1314 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 1315 } 1316 1317 if (TextUtils.isEmpty(keyMgmt)) { 1318 throw new IllegalStateException("Not an EAP network"); 1319 } 1320 1321 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 1322 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 1323 current.enterpriseConfig : null)); 1324 } catch (NullPointerException e) { 1325 throw new IllegalStateException("Invalid config details"); 1326 } 1327 } 1328 1329 private String trimStringForKeyId(String string) { 1330 // Remove quotes and spaces 1331 return string.replace("\"", "").replace(" ", ""); 1332 } 1333 1334 private static BitSet readBitSet(Parcel src) { 1335 int cardinality = src.readInt(); 1336 1337 BitSet set = new BitSet(); 1338 for (int i = 0; i < cardinality; i++) { 1339 set.set(src.readInt()); 1340 } 1341 1342 return set; 1343 } 1344 1345 private static void writeBitSet(Parcel dest, BitSet set) { 1346 int nextSetBit = -1; 1347 1348 dest.writeInt(set.cardinality()); 1349 1350 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1351 dest.writeInt(nextSetBit); 1352 } 1353 } 1354 1355 /** @hide */ 1356 public int getAuthType() { 1357 if (isValid() == false) { 1358 throw new IllegalStateException("Invalid configuration"); 1359 } 1360 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1361 return KeyMgmt.WPA_PSK; 1362 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 1363 return KeyMgmt.WPA2_PSK; 1364 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1365 return KeyMgmt.WPA_EAP; 1366 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1367 return KeyMgmt.IEEE8021X; 1368 } 1369 return KeyMgmt.NONE; 1370 } 1371 1372 /* @hide 1373 * Cache the config key, this seems useful as a speed up since a lot of 1374 * lookups in the config store are done and based on this key. 1375 */ 1376 String mCachedConfigKey; 1377 1378 /** @hide 1379 * return the string used to calculate the hash in WifiConfigStore 1380 * and uniquely identify this WifiConfiguration 1381 */ 1382 public String configKey(boolean allowCached) { 1383 String key; 1384 if (allowCached && mCachedConfigKey != null) { 1385 key = mCachedConfigKey; 1386 } else { 1387 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1388 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1389 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1390 allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1391 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1392 } else if (wepKeys[0] != null) { 1393 key = SSID + "WEP"; 1394 } else { 1395 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1396 } 1397 mCachedConfigKey = key; 1398 } 1399 return key; 1400 } 1401 1402 /** @hide 1403 * get configKey, force calculating the config string 1404 */ 1405 public String configKey() { 1406 return configKey(false); 1407 } 1408 1409 /** @hide 1410 * return the config key string based on a scan result 1411 */ 1412 static public String configKey(ScanResult result) { 1413 String key = "\"" + result.SSID + "\""; 1414 1415 if (result.capabilities.contains("WEP")) { 1416 key = key + "-WEP"; 1417 } 1418 1419 if (result.capabilities.contains("PSK")) { 1420 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1421 } 1422 1423 if (result.capabilities.contains("EAP")) { 1424 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1425 } 1426 1427 return key; 1428 } 1429 1430 /** @hide */ 1431 public IpConfiguration getIpConfiguration() { 1432 return mIpConfiguration; 1433 } 1434 1435 /** @hide */ 1436 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1437 mIpConfiguration = ipConfiguration; 1438 } 1439 1440 /** @hide */ 1441 public StaticIpConfiguration getStaticIpConfiguration() { 1442 return mIpConfiguration.getStaticIpConfiguration(); 1443 } 1444 1445 /** @hide */ 1446 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 1447 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 1448 } 1449 1450 /** @hide */ 1451 public IpConfiguration.IpAssignment getIpAssignment() { 1452 return mIpConfiguration.ipAssignment; 1453 } 1454 1455 /** @hide */ 1456 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1457 mIpConfiguration.ipAssignment = ipAssignment; 1458 } 1459 1460 /** @hide */ 1461 public IpConfiguration.ProxySettings getProxySettings() { 1462 return mIpConfiguration.proxySettings; 1463 } 1464 1465 /** @hide */ 1466 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1467 mIpConfiguration.proxySettings = proxySettings; 1468 } 1469 1470 /** @hide */ 1471 public ProxyInfo getHttpProxy() { 1472 return mIpConfiguration.httpProxy; 1473 } 1474 1475 /** @hide */ 1476 public void setHttpProxy(ProxyInfo httpProxy) { 1477 mIpConfiguration.httpProxy = httpProxy; 1478 } 1479 1480 /** @hide */ 1481 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1482 mIpConfiguration.proxySettings = settings; 1483 mIpConfiguration.httpProxy = proxy; 1484 } 1485 1486 /** Implement the Parcelable interface {@hide} */ 1487 public int describeContents() { 1488 return 0; 1489 } 1490 1491 /** copy constructor {@hide} */ 1492 public WifiConfiguration(WifiConfiguration source) { 1493 if (source != null) { 1494 networkId = source.networkId; 1495 status = source.status; 1496 disableReason = source.disableReason; 1497 disableReason = source.disableReason; 1498 SSID = source.SSID; 1499 BSSID = source.BSSID; 1500 FQDN = source.FQDN; 1501 naiRealm = source.naiRealm; 1502 preSharedKey = source.preSharedKey; 1503 1504 wepKeys = new String[4]; 1505 for (int i = 0; i < wepKeys.length; i++) { 1506 wepKeys[i] = source.wepKeys[i]; 1507 } 1508 1509 wepTxKeyIndex = source.wepTxKeyIndex; 1510 priority = source.priority; 1511 hiddenSSID = source.hiddenSSID; 1512 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 1513 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 1514 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 1515 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 1516 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 1517 1518 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 1519 1520 defaultGwMacAddress = source.defaultGwMacAddress; 1521 1522 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 1523 1524 if ((source.scanResultCache != null) && (source.scanResultCache.size() > 0)) { 1525 scanResultCache = new HashMap<String, ScanResult>(); 1526 scanResultCache.putAll(source.scanResultCache); 1527 } 1528 1529 if ((source.connectChoices != null) && (source.connectChoices.size() > 0)) { 1530 connectChoices = new HashMap<String, Integer>(); 1531 connectChoices.putAll(source.connectChoices); 1532 } 1533 1534 if ((source.linkedConfigurations != null) 1535 && (source.linkedConfigurations.size() > 0)) { 1536 linkedConfigurations = new HashMap<String, Integer>(); 1537 linkedConfigurations.putAll(source.linkedConfigurations); 1538 } 1539 mCachedConfigKey = null; //force null configKey 1540 autoJoinStatus = source.autoJoinStatus; 1541 selfAdded = source.selfAdded; 1542 validatedInternetAccess = source.validatedInternetAccess; 1543 ephemeral = source.ephemeral; 1544 if (source.visibility != null) { 1545 visibility = new Visibility(source.visibility); 1546 } 1547 1548 lastFailure = source.lastFailure; 1549 didSelfAdd = source.didSelfAdd; 1550 lastConnectUid = source.lastConnectUid; 1551 lastUpdateUid = source.lastUpdateUid; 1552 creatorUid = source.creatorUid; 1553 peerWifiConfiguration = source.peerWifiConfiguration; 1554 blackListTimestamp = source.blackListTimestamp; 1555 lastConnected = source.lastConnected; 1556 lastDisconnected = source.lastDisconnected; 1557 lastConnectionFailure = source.lastConnectionFailure; 1558 lastRoamingFailure = source.lastRoamingFailure; 1559 lastRoamingFailureReason = source.lastRoamingFailureReason; 1560 roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli; 1561 numConnectionFailures = source.numConnectionFailures; 1562 numIpConfigFailures = source.numIpConfigFailures; 1563 numAuthFailures = source.numAuthFailures; 1564 numScorerOverride = source.numScorerOverride; 1565 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 1566 numAssociation = source.numAssociation; 1567 numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI; 1568 numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI; 1569 numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI; 1570 numTicksAtLowRSSI = source.numTicksAtLowRSSI; 1571 numTicksAtBadRSSI = source.numTicksAtBadRSSI; 1572 numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI; 1573 numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts; 1574 autoJoinBSSID = source.autoJoinBSSID; 1575 autoJoinUseAggressiveJoinAttemptThreshold 1576 = source.autoJoinUseAggressiveJoinAttemptThreshold; 1577 autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi; 1578 dirty = source.dirty; 1579 numNoInternetAccessReports = source.numNoInternetAccessReports; 1580 } 1581 } 1582 1583 /** {@hide} */ 1584 //public static final int NOTHING_TAG = 0; 1585 /** {@hide} */ 1586 //public static final int SCAN_CACHE_TAG = 1; 1587 1588 /** Implement the Parcelable interface {@hide} */ 1589 @Override 1590 public void writeToParcel(Parcel dest, int flags) { 1591 dest.writeInt(networkId); 1592 dest.writeInt(status); 1593 dest.writeInt(disableReason); 1594 dest.writeString(SSID); 1595 dest.writeString(BSSID); 1596 dest.writeString(autoJoinBSSID); 1597 dest.writeString(FQDN); 1598 dest.writeString(naiRealm); 1599 dest.writeString(preSharedKey); 1600 for (String wepKey : wepKeys) { 1601 dest.writeString(wepKey); 1602 } 1603 dest.writeInt(wepTxKeyIndex); 1604 dest.writeInt(priority); 1605 dest.writeInt(hiddenSSID ? 1 : 0); 1606 dest.writeInt(requirePMF ? 1 : 0); 1607 dest.writeString(updateIdentifier); 1608 1609 writeBitSet(dest, allowedKeyManagement); 1610 writeBitSet(dest, allowedProtocols); 1611 writeBitSet(dest, allowedAuthAlgorithms); 1612 writeBitSet(dest, allowedPairwiseCiphers); 1613 writeBitSet(dest, allowedGroupCiphers); 1614 1615 dest.writeParcelable(enterpriseConfig, flags); 1616 1617 dest.writeParcelable(mIpConfiguration, flags); 1618 dest.writeString(dhcpServer); 1619 dest.writeString(defaultGwMacAddress); 1620 dest.writeInt(autoJoinStatus); 1621 dest.writeInt(selfAdded ? 1 : 0); 1622 dest.writeInt(didSelfAdd ? 1 : 0); 1623 dest.writeInt(validatedInternetAccess ? 1 : 0); 1624 dest.writeInt(ephemeral ? 1 : 0); 1625 dest.writeInt(creatorUid); 1626 dest.writeInt(lastConnectUid); 1627 dest.writeInt(lastUpdateUid); 1628 dest.writeLong(blackListTimestamp); 1629 dest.writeLong(lastConnectionFailure); 1630 dest.writeLong(lastRoamingFailure); 1631 dest.writeInt(lastRoamingFailureReason); 1632 dest.writeLong(roamingFailureBlackListTimeMilli); 1633 dest.writeInt(numConnectionFailures); 1634 dest.writeInt(numIpConfigFailures); 1635 dest.writeInt(numAuthFailures); 1636 dest.writeInt(numScorerOverride); 1637 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 1638 dest.writeInt(numAssociation); 1639 dest.writeInt(numUserTriggeredWifiDisableLowRSSI); 1640 dest.writeInt(numUserTriggeredWifiDisableBadRSSI); 1641 dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI); 1642 dest.writeInt(numTicksAtLowRSSI); 1643 dest.writeInt(numTicksAtBadRSSI); 1644 dest.writeInt(numTicksAtNotHighRSSI); 1645 dest.writeInt(numUserTriggeredJoinAttempts); 1646 dest.writeInt(autoJoinUseAggressiveJoinAttemptThreshold); 1647 dest.writeInt(autoJoinBailedDueToLowRssi ? 1 : 0); 1648 dest.writeInt(numNoInternetAccessReports); 1649 } 1650 1651 /** Implement the Parcelable interface {@hide} */ 1652 public static final Creator<WifiConfiguration> CREATOR = 1653 new Creator<WifiConfiguration>() { 1654 public WifiConfiguration createFromParcel(Parcel in) { 1655 WifiConfiguration config = new WifiConfiguration(); 1656 config.networkId = in.readInt(); 1657 config.status = in.readInt(); 1658 config.disableReason = in.readInt(); 1659 config.SSID = in.readString(); 1660 config.BSSID = in.readString(); 1661 config.autoJoinBSSID = in.readString(); 1662 config.FQDN = in.readString(); 1663 config.naiRealm = in.readString(); 1664 config.preSharedKey = in.readString(); 1665 for (int i = 0; i < config.wepKeys.length; i++) { 1666 config.wepKeys[i] = in.readString(); 1667 } 1668 config.wepTxKeyIndex = in.readInt(); 1669 config.priority = in.readInt(); 1670 config.hiddenSSID = in.readInt() != 0; 1671 config.requirePMF = in.readInt() != 0; 1672 config.updateIdentifier = in.readString(); 1673 1674 config.allowedKeyManagement = readBitSet(in); 1675 config.allowedProtocols = readBitSet(in); 1676 config.allowedAuthAlgorithms = readBitSet(in); 1677 config.allowedPairwiseCiphers = readBitSet(in); 1678 config.allowedGroupCiphers = readBitSet(in); 1679 1680 config.enterpriseConfig = in.readParcelable(null); 1681 1682 config.mIpConfiguration = in.readParcelable(null); 1683 config.dhcpServer = in.readString(); 1684 config.defaultGwMacAddress = in.readString(); 1685 config.autoJoinStatus = in.readInt(); 1686 config.selfAdded = in.readInt() != 0; 1687 config.didSelfAdd = in.readInt() != 0; 1688 config.validatedInternetAccess = in.readInt() != 0; 1689 config.ephemeral = in.readInt() != 0; 1690 config.creatorUid = in.readInt(); 1691 config.lastConnectUid = in.readInt(); 1692 config.lastUpdateUid = in.readInt(); 1693 config.blackListTimestamp = in.readLong(); 1694 config.lastConnectionFailure = in.readLong(); 1695 config.lastRoamingFailure = in.readLong(); 1696 config.lastRoamingFailureReason = in.readInt(); 1697 config.roamingFailureBlackListTimeMilli = in.readLong(); 1698 config.numConnectionFailures = in.readInt(); 1699 config.numIpConfigFailures = in.readInt(); 1700 config.numAuthFailures = in.readInt(); 1701 config.numScorerOverride = in.readInt(); 1702 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 1703 config.numAssociation = in.readInt(); 1704 config.numUserTriggeredWifiDisableLowRSSI = in.readInt(); 1705 config.numUserTriggeredWifiDisableBadRSSI = in.readInt(); 1706 config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt(); 1707 config.numTicksAtLowRSSI = in.readInt(); 1708 config.numTicksAtBadRSSI = in.readInt(); 1709 config.numTicksAtNotHighRSSI = in.readInt(); 1710 config.numUserTriggeredJoinAttempts = in.readInt(); 1711 config.autoJoinUseAggressiveJoinAttemptThreshold = in.readInt(); 1712 config.autoJoinBailedDueToLowRssi = in.readInt() != 0; 1713 config.numNoInternetAccessReports = in.readInt(); 1714 return config; 1715 } 1716 1717 public WifiConfiguration[] newArray(int size) { 1718 return new WifiConfiguration[size]; 1719 } 1720 }; 1721 } 1722