WifiConfiguration.java revision 111fa0274d1d6620f9634783585387f3b773949e
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.net.IpConfiguration; 20import android.net.IpConfiguration.ProxySettings; 21import android.net.IpConfiguration.IpAssignment; 22import android.net.ProxyInfo; 23import android.net.LinkProperties; 24import android.os.Parcel; 25import android.os.Parcelable; 26import android.text.TextUtils; 27 28import java.util.HashMap; 29import java.util.BitSet; 30 31/** 32 * A class representing a configured Wi-Fi network, including the 33 * security configuration. 34 */ 35public class WifiConfiguration implements Parcelable { 36 private static final String TAG = "WifiConfiguration"; 37 /** {@hide} */ 38 public static final String ssidVarName = "ssid"; 39 /** {@hide} */ 40 public static final String bssidVarName = "bssid"; 41 /** {@hide} */ 42 public static final String pskVarName = "psk"; 43 /** {@hide} */ 44 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 45 /** {@hide} */ 46 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 47 /** {@hide} */ 48 public static final String priorityVarName = "priority"; 49 /** {@hide} */ 50 public static final String hiddenSSIDVarName = "scan_ssid"; 51 /** {@hide} */ 52 public static final int INVALID_NETWORK_ID = -1; 53 /** 54 * Recognized key management schemes. 55 */ 56 public static class KeyMgmt { 57 private KeyMgmt() { } 58 59 /** WPA is not used; plaintext or static WEP could be used. */ 60 public static final int NONE = 0; 61 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 62 public static final int WPA_PSK = 1; 63 /** WPA using EAP authentication. Generally used with an external authentication server. */ 64 public static final int WPA_EAP = 2; 65 /** IEEE 802.1X using EAP authentication and (optionally) dynamically 66 * generated WEP keys. */ 67 public static final int IEEE8021X = 3; 68 69 /** WPA2 pre-shared key for use with soft access point 70 * (requires {@code preSharedKey} to be specified). 71 * @hide 72 */ 73 public static final int WPA2_PSK = 4; 74 75 public static final String varName = "key_mgmt"; 76 77 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", 78 "WPA2_PSK" }; 79 } 80 81 /** 82 * Recognized security protocols. 83 */ 84 public static class Protocol { 85 private Protocol() { } 86 87 /** WPA/IEEE 802.11i/D3.0 */ 88 public static final int WPA = 0; 89 /** WPA2/IEEE 802.11i */ 90 public static final int RSN = 1; 91 92 public static final String varName = "proto"; 93 94 public static final String[] strings = { "WPA", "RSN" }; 95 } 96 97 /** 98 * Recognized IEEE 802.11 authentication algorithms. 99 */ 100 public static class AuthAlgorithm { 101 private AuthAlgorithm() { } 102 103 /** Open System authentication (required for WPA/WPA2) */ 104 public static final int OPEN = 0; 105 /** Shared Key authentication (requires static WEP keys) */ 106 public static final int SHARED = 1; 107 /** LEAP/Network EAP (only used with LEAP) */ 108 public static final int LEAP = 2; 109 110 public static final String varName = "auth_alg"; 111 112 public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; 113 } 114 115 /** 116 * Recognized pairwise ciphers for WPA. 117 */ 118 public static class PairwiseCipher { 119 private PairwiseCipher() { } 120 121 /** Use only Group keys (deprecated) */ 122 public static final int NONE = 0; 123 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 124 public static final int TKIP = 1; 125 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 126 public static final int CCMP = 2; 127 128 public static final String varName = "pairwise"; 129 130 public static final String[] strings = { "NONE", "TKIP", "CCMP" }; 131 } 132 133 /** 134 * Recognized group ciphers. 135 * <pre> 136 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 137 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 138 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 139 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 140 * </pre> 141 */ 142 public static class GroupCipher { 143 private GroupCipher() { } 144 145 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */ 146 public static final int WEP40 = 0; 147 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */ 148 public static final int WEP104 = 1; 149 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 150 public static final int TKIP = 2; 151 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 152 public static final int CCMP = 3; 153 154 public static final String varName = "group"; 155 156 public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" }; 157 } 158 159 /** Possible status of a network configuration. */ 160 public static class Status { 161 private Status() { } 162 163 /** this is the network we are currently connected to */ 164 public static final int CURRENT = 0; 165 /** supplicant will not attempt to use this network */ 166 public static final int DISABLED = 1; 167 /** supplicant will consider this network available for association */ 168 public static final int ENABLED = 2; 169 170 public static final String[] strings = { "current", "disabled", "enabled" }; 171 } 172 173 /** @hide */ 174 public static final int DISABLED_UNKNOWN_REASON = 0; 175 /** @hide */ 176 public static final int DISABLED_DNS_FAILURE = 1; 177 /** @hide */ 178 public static final int DISABLED_DHCP_FAILURE = 2; 179 /** @hide */ 180 public static final int DISABLED_AUTH_FAILURE = 3; 181 /** @hide */ 182 public static final int DISABLED_ASSOCIATION_REJECT = 4; 183 184 /** 185 * The ID number that the supplicant uses to identify this 186 * network configuration entry. This must be passed as an argument 187 * to most calls into the supplicant. 188 */ 189 public int networkId; 190 191 /** 192 * The current status of this network configuration entry. 193 * @see Status 194 */ 195 public int status; 196 197 /** 198 * The code referring to a reason for disabling the network 199 * Valid when {@link #status} == Status.DISABLED 200 * @hide 201 */ 202 public int disableReason; 203 204 /** 205 * The network's SSID. Can either be an ASCII string, 206 * which must be enclosed in double quotation marks 207 * (e.g., {@code "MyNetwork"}, or a string of 208 * hex digits,which are not enclosed in quotes 209 * (e.g., {@code 01a243f405}). 210 */ 211 public String SSID; 212 /** 213 * When set, this network configuration entry should only be used when 214 * associating with the AP having the specified BSSID. The value is 215 * a string in the format of an Ethernet MAC address, e.g., 216 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 217 */ 218 public String BSSID; 219 /** 220 * Fully qualified domain name (FQDN), for Passpoint credential. 221 * e.g. {@code "mail.example.com"}. 222 * @hide 223 */ 224 public String FQDN; 225 /** 226 * Network access identifier (NAI) realm, for Passpoint credential. 227 * e.g. {@code "myhost.example.com"}. 228 * @hide 229 */ 230 public String naiRealm; 231 232 /** 233 * Pre-shared key for use with WPA-PSK. 234 * <p/> 235 * When the value of this key is read, the actual key is 236 * not returned, just a "*" if the key has a value, or the null 237 * string otherwise. 238 */ 239 public String preSharedKey; 240 /** 241 * Up to four WEP keys. Either an ASCII string enclosed in double 242 * quotation marks (e.g., {@code "abcdef"} or a string 243 * of hex digits (e.g., {@code 0102030405}). 244 * <p/> 245 * When the value of one of these keys is read, the actual key is 246 * not returned, just a "*" if the key has a value, or the null 247 * string otherwise. 248 */ 249 public String[] wepKeys; 250 251 /** Default WEP key index, ranging from 0 to 3. */ 252 public int wepTxKeyIndex; 253 254 /** 255 * Priority determines the preference given to a network by {@code wpa_supplicant} 256 * when choosing an access point with which to associate. 257 */ 258 public int priority; 259 260 /** 261 * This is a network that does not broadcast its SSID, so an 262 * SSID-specific probe request must be used for scans. 263 */ 264 public boolean hiddenSSID; 265 266 /** 267 * The set of key management protocols supported by this configuration. 268 * See {@link KeyMgmt} for descriptions of the values. 269 * Defaults to WPA-PSK WPA-EAP. 270 */ 271 public BitSet allowedKeyManagement; 272 /** 273 * The set of security protocols supported by this configuration. 274 * See {@link Protocol} for descriptions of the values. 275 * Defaults to WPA RSN. 276 */ 277 public BitSet allowedProtocols; 278 /** 279 * The set of authentication protocols supported by this configuration. 280 * See {@link AuthAlgorithm} for descriptions of the values. 281 * Defaults to automatic selection. 282 */ 283 public BitSet allowedAuthAlgorithms; 284 /** 285 * The set of pairwise ciphers for WPA supported by this configuration. 286 * See {@link PairwiseCipher} for descriptions of the values. 287 * Defaults to CCMP TKIP. 288 */ 289 public BitSet allowedPairwiseCiphers; 290 /** 291 * The set of group ciphers supported by this configuration. 292 * See {@link GroupCipher} for descriptions of the values. 293 * Defaults to CCMP TKIP WEP104 WEP40. 294 */ 295 public BitSet allowedGroupCiphers; 296 /** 297 * The enterprise configuration details specifying the EAP method, 298 * certificates and other settings associated with the EAP. 299 */ 300 public WifiEnterpriseConfig enterpriseConfig; 301 302 /** 303 * @hide 304 */ 305 private IpConfiguration mIpConfiguration; 306 307 /** 308 * @hide 309 * dhcp server MAC address if known 310 */ 311 public String dhcpServer; 312 313 /** 314 * @hide 315 * default Gateway MAC address if known 316 */ 317 public String defaultGwMacAddress; 318 319 /** 320 * @hide 321 * last failure 322 */ 323 public String lastFailure; 324 325 /** 326 * @hide 327 * Uid of app creating the configuration 328 */ 329 public int creatorUid; 330 331 /** 332 * @hide 333 * Uid of last app issuing a connection related command 334 */ 335 public int lastConnectUid; 336 337 /** 338 * @hide 339 * Uid of last app modifying the configuration 340 */ 341 public int lastUpdateUid; 342 343 /** 344 * @hide 345 * BSSID list on which this configuration was seen. 346 * TODO: prevent this list to grow infinitely, age-out the results 347 */ 348 public HashMap<String, ScanResult> scanResultCache; 349 350 /** The Below RSSI thresholds are used to configure AutoJoin 351 * - GOOD/LOW/BAD thresholds are used so as to calculate link score 352 * - UNWANTED_SOFT are used by the blacklisting logic so as to handle the unwanted network message coming from CS 353 * - UNBLACKLIST thresholds are used so as to tweak the speed at which the network is unblacklisted (i.e. if 354 * it is seen with good RSSI, it is blacklisted faster) 355 * - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from the network we need to be before autojoin kicks in 356 */ 357 /** @hide **/ 358 public static int INVALID_RSSI = -127; 359 360 /** @hide **/ 361 public static int UNWANTED_BLACKLIST_SOFT_RSSI_24 = -80; 362 363 /** @hide **/ 364 public static int UNWANTED_BLACKLIST_SOFT_RSSI_5 = -70; 365 366 /** @hide **/ 367 public static int GOOD_RSSI_24 = -65; 368 369 /** @hide **/ 370 public static int LOW_RSSI_24 = -75; 371 372 /** @hide **/ 373 public static int BAD_RSSI_24 = -85; 374 375 /** @hide **/ 376 public static int GOOD_RSSI_5 = -55; 377 378 /** @hide **/ 379 public static int LOW_RSSI_5 = -65; 380 381 /** @hide **/ 382 public static int BAD_RSSI_5 = -75; 383 384 /** @hide **/ 385 public static int UNWANTED_BLACKLIST_SOFT_BUMP = 4; 386 387 /** @hide **/ 388 public static int UNWANTED_BLACKLIST_HARD_BUMP = 8; 389 390 /** @hide **/ 391 public static int UNBLACKLIST_THRESHOLD_24_SOFT = -75; 392 393 /** @hide **/ 394 public static int UNBLACKLIST_THRESHOLD_24_HARD = -68; 395 396 /** @hide **/ 397 public static int UNBLACKLIST_THRESHOLD_5_SOFT = -63; 398 399 /** @hide **/ 400 public static int UNBLACKLIST_THRESHOLD_5_HARD = -56; 401 402 /** @hide **/ 403 public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_24 = -80; 404 405 /** @hide **/ 406 public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_5 = -70; 407 408 /** @hide 409 * 5GHz band is prefered over 2.4 if the 5GHz RSSI is higher than this threshold **/ 410 public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65; 411 412 /** 413 * @hide 414 * A summary of the RSSI and Band status for that configuration 415 * This is used as a temporary value by the auto-join controller 416 */ 417 public final class Visibility { 418 public int rssi5; // strongest 5GHz RSSI 419 public int rssi24; // strongest 2.4GHz RSSI 420 public int num5; // number of BSSIDs on 5GHz 421 public int num24; // number of BSSIDs on 2.4GHz 422 public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen) 423 public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen) 424 425 public Visibility() { 426 rssi5 = INVALID_RSSI; 427 rssi24 = INVALID_RSSI; 428 } 429 430 public Visibility(Visibility source) { 431 rssi5 = source.rssi5; 432 rssi24 = source.rssi24; 433 age24 = source.age24; 434 age5 = source.age5; 435 num24 = source.num24; 436 num5 = source.num5; 437 } 438 439 @Override 440 public String toString() { 441 StringBuilder sbuf = new StringBuilder(); 442 sbuf.append("["); 443 if (rssi24 > INVALID_RSSI) { 444 sbuf.append(Integer.toString(rssi24)); 445 sbuf.append(","); 446 sbuf.append(Integer.toString(num24)); 447 } else { 448 sbuf.append("*"); 449 } 450 sbuf.append(" - "); 451 if (rssi5 > INVALID_RSSI) { 452 sbuf.append(Integer.toString(rssi5)); 453 sbuf.append(","); 454 sbuf.append(Integer.toString(num5)); 455 } 456 sbuf.append("]"); 457 return sbuf.toString(); 458 } 459 } 460 461 /** @hide 462 * Cache the visibility status of this configuration. 463 * Visibility can change at any time depending on scan results availability. 464 * Owner of the WifiConfiguration is responsible to set this field based on 465 * recent scan results. 466 ***/ 467 public Visibility visibility; 468 469 /** @hide 470 * calculate and set Visibility for that configuration. 471 * 472 * age in milliseconds: we will consider only ScanResults that are more recent, 473 * i.e. younger. 474 ***/ 475 public Visibility setVisibility(long age) { 476 if (scanResultCache == null) { 477 visibility = null; 478 return null; 479 } 480 481 Visibility status = new Visibility(); 482 483 long now_ms = System.currentTimeMillis(); 484 for(ScanResult result : scanResultCache.values()) { 485 if (result.seen == 0) 486 continue; 487 488 if (result.is5GHz()) { 489 //strictly speaking: [4915, 5825] 490 //number of known BSSID on 5GHz band 491 status.num5 = status.num5 + 1; 492 } else if (result.is24GHz()) { 493 //strictly speaking: [2412, 2482] 494 //number of known BSSID on 2.4Ghz band 495 status.num24 = status.num24 + 1; 496 } 497 498 if ((now_ms - result.seen) > age) continue; 499 500 if (result.is5GHz()) { 501 if (result.level > status.rssi5) { 502 status.rssi5 = result.level; 503 status.age5 = result.seen; 504 } 505 } else if (result.is24GHz()) { 506 if (result.level > status.rssi24) { 507 status.rssi24 = result.level; 508 status.age24 = result.seen; 509 } 510 } 511 } 512 visibility = status; 513 return status; 514 } 515 516 /** @hide */ 517 public static final int AUTO_JOIN_ENABLED = 0; 518 /** 519 * if this is set, the WifiConfiguration cannot use linkages so as to bump 520 * it's relative priority. 521 * - status between and 128 indicate various level of blacklisting depending 522 * on the severity or frequency of the connection error 523 * - deleted status indicates that the user is deleting the configuration, and so 524 * although it may have been self added we will not re-self-add it, ignore it, 525 * not return it to applications, and not connect to it 526 * */ 527 528 /** @hide 529 * network was temporary disabled due to bad connection, most likely due 530 * to weak RSSI */ 531 public static final int AUTO_JOIN_TEMPORARY_DISABLED = 1; 532 /** @hide 533 * network was temporary disabled due to bad connection, which cant be attributed 534 * to weak RSSI */ 535 public static final int AUTO_JOIN_TEMPORARY_DISABLED_LINK_ERRORS = 32; 536 /** @hide */ 537 public static final int AUTO_JOIN_TEMPORARY_DISABLED_AT_SUPPLICANT = 64; 538 /** @hide */ 539 public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE = 128; 540 /** @hide */ 541 public static final int AUTO_JOIN_DELETED = 200; 542 543 /** 544 * @hide 545 */ 546 public int autoJoinStatus; 547 548 549 /** 550 * @hide 551 */ 552 public long blackListTimestamp; 553 554 /** 555 * @hide 556 * last time the system was connected to this configuration. 557 */ 558 public long lastConnected; 559 560 /** 561 * @hide 562 * last time the system was disconnected to this configuration. 563 */ 564 public long lastDisconnected; 565 566 /** 567 * Set if the configuration was self added by the framework 568 * This boolean is cleared if we get a connect/save/ update or 569 * any wifiManager command that indicate the user interacted with the configuration 570 * since we will now consider that the configuration belong to him. 571 * @hide 572 */ 573 public boolean selfAdded; 574 575 /** 576 * Set if the configuration was self added by the framework 577 * This boolean is set once and never cleared. It is used 578 * so as we never loose track of who created the 579 * configuration in the first place. 580 * @hide 581 */ 582 public boolean didSelfAdd; 583 584 /** 585 * peer WifiConfiguration this WifiConfiguration was added for 586 * @hide 587 */ 588 public String peerWifiConfiguration; 589 590 /** 591 * @hide 592 * Indicate that a WifiConfiguration is temporary and should not be saved 593 * nor considered by AutoJoin. 594 */ 595 public boolean ephemeral; 596 597 /** 598 * @hide 599 * Connect choices 600 * 601 * remember the keys identifying the known WifiConfiguration over which this configuration 602 * was preferred by user or a "WiFi Network Management app", that is, 603 * a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration 604 * was visible to the user: 605 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 606 * 607 * The integer represents the configuration's RSSI at that time (useful?) 608 * 609 * The overall auto-join algorithm make use of past connect choice so as to sort configuration, 610 * the exact algorithm still fluctuating as of 5/7/2014 611 * 612 */ 613 public HashMap<String, Integer> connectChoices; 614 615 /** 616 * @hide 617 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 618 * regarding roaming and auto-joining. 619 * The linked configuration may or may not have same SSID, and may or may not have same 620 * credentials. 621 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 622 */ 623 public HashMap<String, Integer> linkedConfigurations; 624 625 public WifiConfiguration() { 626 networkId = INVALID_NETWORK_ID; 627 SSID = null; 628 BSSID = null; 629 FQDN = null; 630 naiRealm = null; 631 priority = 0; 632 hiddenSSID = false; 633 disableReason = DISABLED_UNKNOWN_REASON; 634 allowedKeyManagement = new BitSet(); 635 allowedProtocols = new BitSet(); 636 allowedAuthAlgorithms = new BitSet(); 637 allowedPairwiseCiphers = new BitSet(); 638 allowedGroupCiphers = new BitSet(); 639 wepKeys = new String[4]; 640 for (int i = 0; i < wepKeys.length; i++) { 641 wepKeys[i] = null; 642 } 643 enterpriseConfig = new WifiEnterpriseConfig(); 644 autoJoinStatus = AUTO_JOIN_ENABLED; 645 selfAdded = false; 646 didSelfAdd = false; 647 ephemeral = false; 648 mIpConfiguration = new IpConfiguration(); 649 } 650 651 /** 652 * indicates whether the configuration is valid 653 * @return true if valid, false otherwise 654 * @hide 655 */ 656 public boolean isValid() { 657 658 if (allowedKeyManagement == null) 659 return false; 660 661 if (allowedKeyManagement.cardinality() > 1) { 662 if (allowedKeyManagement.cardinality() != 2) { 663 return false; 664 } 665 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) { 666 return false; 667 } 668 if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false) 669 && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) { 670 return false; 671 } 672 } 673 674 // TODO: Add more checks 675 return true; 676 } 677 678 /** 679 * Helper function, identify if a configuration is linked 680 * @hide 681 */ 682 public boolean isLinked(WifiConfiguration config) { 683 if (config.linkedConfigurations != null && linkedConfigurations != null) { 684 if (config.linkedConfigurations.get(configKey()) != null 685 && linkedConfigurations.get(config.configKey()) != null) { 686 return true; 687 } 688 } 689 return false; 690 } 691 692 /** 693 * most recent time we have seen this configuration 694 * @return most recent scanResult 695 * @hide 696 */ 697 public ScanResult lastSeen() { 698 ScanResult mostRecent = null; 699 700 if (scanResultCache == null) { 701 return null; 702 } 703 704 for (ScanResult result : scanResultCache.values()) { 705 if (mostRecent == null) { 706 if (result.seen != 0) 707 mostRecent = result; 708 } else { 709 if (result.seen > mostRecent.seen) { 710 mostRecent = result; 711 } 712 } 713 } 714 return mostRecent; 715 } 716 717 /** @hide **/ 718 public void setAutoJoinStatus(int status) { 719 if (status < 0) status = 0; 720 if (status == 0) { 721 blackListTimestamp = 0; 722 } else if (status > autoJoinStatus) { 723 blackListTimestamp = System.currentTimeMillis(); 724 } 725 autoJoinStatus = status; 726 } 727 728 @Override 729 public String toString() { 730 StringBuilder sbuf = new StringBuilder(); 731 if (this.status == WifiConfiguration.Status.CURRENT) { 732 sbuf.append("* "); 733 } else if (this.status == WifiConfiguration.Status.DISABLED) { 734 sbuf.append("- DSBLE: ").append(this.disableReason).append(" "); 735 } 736 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 737 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN). 738 append(" REALM: ").append(this.naiRealm).append(" PRIO: ").append(this.priority). 739 append('\n'); 740 sbuf.append(" KeyMgmt:"); 741 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 742 if (this.allowedKeyManagement.get(k)) { 743 sbuf.append(" "); 744 if (k < KeyMgmt.strings.length) { 745 sbuf.append(KeyMgmt.strings[k]); 746 } else { 747 sbuf.append("??"); 748 } 749 } 750 } 751 sbuf.append(" Protocols:"); 752 for (int p = 0; p < this.allowedProtocols.size(); p++) { 753 if (this.allowedProtocols.get(p)) { 754 sbuf.append(" "); 755 if (p < Protocol.strings.length) { 756 sbuf.append(Protocol.strings[p]); 757 } else { 758 sbuf.append("??"); 759 } 760 } 761 } 762 sbuf.append('\n'); 763 sbuf.append(" AuthAlgorithms:"); 764 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 765 if (this.allowedAuthAlgorithms.get(a)) { 766 sbuf.append(" "); 767 if (a < AuthAlgorithm.strings.length) { 768 sbuf.append(AuthAlgorithm.strings[a]); 769 } else { 770 sbuf.append("??"); 771 } 772 } 773 } 774 sbuf.append('\n'); 775 sbuf.append(" PairwiseCiphers:"); 776 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 777 if (this.allowedPairwiseCiphers.get(pc)) { 778 sbuf.append(" "); 779 if (pc < PairwiseCipher.strings.length) { 780 sbuf.append(PairwiseCipher.strings[pc]); 781 } else { 782 sbuf.append("??"); 783 } 784 } 785 } 786 sbuf.append('\n'); 787 sbuf.append(" GroupCiphers:"); 788 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 789 if (this.allowedGroupCiphers.get(gc)) { 790 sbuf.append(" "); 791 if (gc < GroupCipher.strings.length) { 792 sbuf.append(GroupCipher.strings[gc]); 793 } else { 794 sbuf.append("??"); 795 } 796 } 797 } 798 sbuf.append('\n').append(" PSK: "); 799 if (this.preSharedKey != null) { 800 sbuf.append('*'); 801 } 802 803 sbuf.append(enterpriseConfig); 804 sbuf.append('\n'); 805 806 sbuf.append(mIpConfiguration.toString()); 807 808 if (selfAdded) sbuf.append("selfAdded"); 809 if (creatorUid != 0) sbuf.append("uid=" + Integer.toString(creatorUid)); 810 811 if (blackListTimestamp != 0) { 812 long now_ms = System.currentTimeMillis(); 813 long diff = now_ms - blackListTimestamp; 814 if (diff <= 0) { 815 sbuf.append("blackListed since <incorrect>"); 816 } else { 817 sbuf.append("blackListed since ").append(Long.toString(diff/1000)).append( "sec"); 818 } 819 } 820 821 return sbuf.toString(); 822 } 823 824 /** 825 * Construct a WifiConfiguration from a scanned network 826 * @param scannedAP the scan result used to construct the config entry 827 * TODO: figure out whether this is a useful way to construct a new entry. 828 * 829 public WifiConfiguration(ScanResult scannedAP) { 830 networkId = -1; 831 SSID = scannedAP.SSID; 832 BSSID = scannedAP.BSSID; 833 } 834 */ 835 836 /** {@hide} */ 837 public String getPrintableSsid() { 838 if (SSID == null) return ""; 839 final int length = SSID.length(); 840 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 841 return SSID.substring(1, length - 1); 842 } 843 844 /** The ascii-encoded string format is P"<ascii-encoded-string>" 845 * The decoding is implemented in the supplicant for a newly configured 846 * network. 847 */ 848 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 849 (SSID.charAt(length-1) == '"')) { 850 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 851 SSID.substring(2, length - 1)); 852 return wifiSsid.toString(); 853 } 854 return SSID; 855 } 856 857 /** 858 * Get an identifier for associating credentials with this config 859 * @param current configuration contains values for additional fields 860 * that are not part of this configuration. Used 861 * when a config with some fields is passed by an application. 862 * @throws IllegalStateException if config is invalid for key id generation 863 * @hide 864 */ 865 public String getKeyIdForCredentials(WifiConfiguration current) { 866 String keyMgmt = null; 867 868 try { 869 // Get current config details for fields that are not initialized 870 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 871 if (allowedKeyManagement.cardinality() == 0) { 872 allowedKeyManagement = current.allowedKeyManagement; 873 } 874 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 875 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 876 } 877 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 878 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 879 } 880 881 if (TextUtils.isEmpty(keyMgmt)) { 882 throw new IllegalStateException("Not an EAP network"); 883 } 884 885 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 886 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 887 current.enterpriseConfig : null)); 888 } catch (NullPointerException e) { 889 throw new IllegalStateException("Invalid config details"); 890 } 891 } 892 893 private String trimStringForKeyId(String string) { 894 // Remove quotes and spaces 895 return string.replace("\"", "").replace(" ", ""); 896 } 897 898 private static BitSet readBitSet(Parcel src) { 899 int cardinality = src.readInt(); 900 901 BitSet set = new BitSet(); 902 for (int i = 0; i < cardinality; i++) { 903 set.set(src.readInt()); 904 } 905 906 return set; 907 } 908 909 private static void writeBitSet(Parcel dest, BitSet set) { 910 int nextSetBit = -1; 911 912 dest.writeInt(set.cardinality()); 913 914 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 915 dest.writeInt(nextSetBit); 916 } 917 } 918 919 /** @hide */ 920 public int getAuthType() { 921 if (isValid() == false) { 922 throw new IllegalStateException("Invalid configuration"); 923 } 924 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 925 return KeyMgmt.WPA_PSK; 926 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 927 return KeyMgmt.WPA2_PSK; 928 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 929 return KeyMgmt.WPA_EAP; 930 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 931 return KeyMgmt.IEEE8021X; 932 } 933 return KeyMgmt.NONE; 934 } 935 936 /* @hide 937 * Cache the config key, this seems useful as a speed up since a lot of 938 * lookups in the config store are done and based on this key. 939 */ 940 String mCachedConfigKey; 941 942 /** @hide 943 * return the string used to calculate the hash in WifiConfigStore 944 * and uniquely identify this WifiConfiguration 945 */ 946 public String configKey(boolean allowCached) { 947 String key; 948 if (allowCached && mCachedConfigKey != null) { 949 key = mCachedConfigKey; 950 } else { 951 key = this.SSID; 952 if (key == null) 953 key = ""; 954 if (this.wepKeys[0] != null) { 955 key = key + "-WEP"; 956 } 957 if (this.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 958 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 959 } 960 if (this.allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 961 this.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 962 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 963 } 964 mCachedConfigKey = key; 965 } 966 return key; 967 } 968 969 /** @hide 970 * get configKey, force calculating the config string 971 */ 972 public String configKey() { 973 return configKey(false); 974 } 975 976 /** @hide 977 * return the config key string based on a scan result 978 */ 979 static public String configKey(ScanResult result) { 980 String key = "\"" + result.SSID + "\""; 981 982 if (result.capabilities.contains("WEP")) { 983 key = key + "-WEP"; 984 } 985 986 if (result.capabilities.contains("PSK")) { 987 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 988 } 989 990 if (result.capabilities.contains("EAP")) { 991 key = key + "-" + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 992 } 993 994 return key; 995 } 996 997 /** @hide */ 998 public IpConfiguration getIpConfiguration() { 999 return mIpConfiguration; 1000 } 1001 1002 /** @hide */ 1003 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1004 mIpConfiguration = ipConfiguration; 1005 } 1006 1007 /** @hide */ 1008 public LinkProperties getLinkProperties() { 1009 return mIpConfiguration.linkProperties; 1010 } 1011 1012 /** @hide */ 1013 public void setLinkProperties(LinkProperties linkProperties) { 1014 mIpConfiguration.linkProperties = linkProperties; 1015 } 1016 1017 /** @hide */ 1018 public IpConfiguration.IpAssignment getIpAssignment() { 1019 return mIpConfiguration.ipAssignment; 1020 } 1021 1022 /** @hide */ 1023 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1024 mIpConfiguration.ipAssignment = ipAssignment; 1025 } 1026 1027 /** @hide */ 1028 public IpConfiguration.ProxySettings getProxySettings() { 1029 return mIpConfiguration.proxySettings; 1030 } 1031 1032 /** @hide */ 1033 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1034 mIpConfiguration.proxySettings = proxySettings; 1035 } 1036 1037 /** @hide */ 1038 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1039 mIpConfiguration.proxySettings = settings; 1040 mIpConfiguration.linkProperties.setHttpProxy(proxy); 1041 } 1042 1043 /** Implement the Parcelable interface {@hide} */ 1044 public int describeContents() { 1045 return 0; 1046 } 1047 1048 /** copy constructor {@hide} */ 1049 public WifiConfiguration(WifiConfiguration source) { 1050 if (source != null) { 1051 networkId = source.networkId; 1052 status = source.status; 1053 disableReason = source.disableReason; 1054 disableReason = source.disableReason; 1055 SSID = source.SSID; 1056 BSSID = source.BSSID; 1057 FQDN = source.FQDN; 1058 naiRealm = source.naiRealm; 1059 preSharedKey = source.preSharedKey; 1060 1061 wepKeys = new String[4]; 1062 for (int i = 0; i < wepKeys.length; i++) { 1063 wepKeys[i] = source.wepKeys[i]; 1064 } 1065 1066 wepTxKeyIndex = source.wepTxKeyIndex; 1067 priority = source.priority; 1068 hiddenSSID = source.hiddenSSID; 1069 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 1070 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 1071 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 1072 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 1073 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 1074 1075 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 1076 1077 defaultGwMacAddress = source.defaultGwMacAddress; 1078 1079 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 1080 1081 if ((source.scanResultCache != null) && (source.scanResultCache.size() > 0)) { 1082 scanResultCache = new HashMap<String, ScanResult>(); 1083 scanResultCache.putAll(source.scanResultCache); 1084 } 1085 1086 if ((source.connectChoices != null) && (source.connectChoices.size() > 0)) { 1087 connectChoices = new HashMap<String, Integer>(); 1088 connectChoices.putAll(source.connectChoices); 1089 } 1090 1091 if ((source.linkedConfigurations != null) 1092 && (source.linkedConfigurations.size() > 0)) { 1093 linkedConfigurations = new HashMap<String, Integer>(); 1094 linkedConfigurations.putAll(source.linkedConfigurations); 1095 } 1096 mCachedConfigKey = null; //force null configKey 1097 autoJoinStatus = source.autoJoinStatus; 1098 selfAdded = source.selfAdded; 1099 1100 if (source.visibility != null) { 1101 visibility = new Visibility(source.visibility); 1102 } 1103 1104 lastFailure = source.lastFailure; 1105 didSelfAdd = source.didSelfAdd; 1106 lastConnectUid = source.lastConnectUid; 1107 lastUpdateUid = source.lastUpdateUid; 1108 creatorUid = source.creatorUid; 1109 peerWifiConfiguration = source.peerWifiConfiguration; 1110 blackListTimestamp = source.blackListTimestamp; 1111 lastConnected = source.lastConnected; 1112 lastDisconnected = source.lastDisconnected; 1113 } 1114 } 1115 1116 /** {@hide} */ 1117 //public static final int NOTHING_TAG = 0; 1118 /** {@hide} */ 1119 //public static final int SCAN_CACHE_TAG = 1; 1120 1121 /** Implement the Parcelable interface {@hide} */ 1122 @Override 1123 public void writeToParcel(Parcel dest, int flags) { 1124 dest.writeInt(networkId); 1125 dest.writeInt(status); 1126 dest.writeInt(disableReason); 1127 dest.writeString(SSID); 1128 dest.writeString(BSSID); 1129 dest.writeString(FQDN); 1130 dest.writeString(naiRealm); 1131 dest.writeString(preSharedKey); 1132 for (String wepKey : wepKeys) { 1133 dest.writeString(wepKey); 1134 } 1135 dest.writeInt(wepTxKeyIndex); 1136 dest.writeInt(priority); 1137 dest.writeInt(hiddenSSID ? 1 : 0); 1138 1139 writeBitSet(dest, allowedKeyManagement); 1140 writeBitSet(dest, allowedProtocols); 1141 writeBitSet(dest, allowedAuthAlgorithms); 1142 writeBitSet(dest, allowedPairwiseCiphers); 1143 writeBitSet(dest, allowedGroupCiphers); 1144 1145 dest.writeParcelable(enterpriseConfig, flags); 1146 1147 dest.writeParcelable(mIpConfiguration, flags); 1148 dest.writeString(dhcpServer); 1149 dest.writeString(defaultGwMacAddress); 1150 dest.writeInt(autoJoinStatus); 1151 dest.writeInt(selfAdded ? 1 : 0); 1152 dest.writeInt(didSelfAdd ? 1 : 0); 1153 dest.writeInt(creatorUid); 1154 dest.writeInt(lastConnectUid); 1155 dest.writeInt(lastUpdateUid); 1156 dest.writeLong(blackListTimestamp); 1157 } 1158 1159 /** Implement the Parcelable interface {@hide} */ 1160 public static final Creator<WifiConfiguration> CREATOR = 1161 new Creator<WifiConfiguration>() { 1162 public WifiConfiguration createFromParcel(Parcel in) { 1163 WifiConfiguration config = new WifiConfiguration(); 1164 config.networkId = in.readInt(); 1165 config.status = in.readInt(); 1166 config.disableReason = in.readInt(); 1167 config.SSID = in.readString(); 1168 config.BSSID = in.readString(); 1169 config.FQDN = in.readString(); 1170 config.naiRealm = in.readString(); 1171 config.preSharedKey = in.readString(); 1172 for (int i = 0; i < config.wepKeys.length; i++) { 1173 config.wepKeys[i] = in.readString(); 1174 } 1175 config.wepTxKeyIndex = in.readInt(); 1176 config.priority = in.readInt(); 1177 config.hiddenSSID = in.readInt() != 0; 1178 config.allowedKeyManagement = readBitSet(in); 1179 config.allowedProtocols = readBitSet(in); 1180 config.allowedAuthAlgorithms = readBitSet(in); 1181 config.allowedPairwiseCiphers = readBitSet(in); 1182 config.allowedGroupCiphers = readBitSet(in); 1183 1184 config.enterpriseConfig = in.readParcelable(null); 1185 1186 config.mIpConfiguration = in.readParcelable(null); 1187 config.dhcpServer = in.readString(); 1188 config.defaultGwMacAddress = in.readString(); 1189 config.autoJoinStatus = in.readInt(); 1190 config.selfAdded = in.readInt() != 0; 1191 config.didSelfAdd = in.readInt() != 0; 1192 config.creatorUid = in.readInt(); 1193 config.lastConnectUid = in.readInt(); 1194 config.lastUpdateUid = in.readInt(); 1195 config.blackListTimestamp = in.readLong(); 1196 return config; 1197 } 1198 1199 public WifiConfiguration[] newArray(int size) { 1200 return new WifiConfiguration[size]; 1201 } 1202 }; 1203} 1204