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