1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.wifi; 18 19 import android.annotation.SystemApi; 20 import android.content.pm.PackageManager; 21 import android.net.IpConfiguration; 22 import android.net.IpConfiguration.ProxySettings; 23 import android.net.ProxyInfo; 24 import android.net.StaticIpConfiguration; 25 import android.net.Uri; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.os.UserHandle; 29 import android.text.TextUtils; 30 import android.util.BackupUtils; 31 32 import java.io.ByteArrayOutputStream; 33 import java.io.DataInputStream; 34 import java.io.DataOutputStream; 35 import java.io.IOException; 36 import java.util.Arrays; 37 import java.util.BitSet; 38 import java.util.HashMap; 39 40 /** 41 * A class representing a configured Wi-Fi network, including the 42 * security configuration. 43 */ 44 public class WifiConfiguration implements Parcelable { 45 private static final String TAG = "WifiConfiguration"; 46 /** 47 * Current Version of the Backup Serializer. 48 */ 49 private static final int BACKUP_VERSION = 2; 50 /** {@hide} */ 51 public static final String ssidVarName = "ssid"; 52 /** {@hide} */ 53 public static final String bssidVarName = "bssid"; 54 /** {@hide} */ 55 public static final String pskVarName = "psk"; 56 /** {@hide} */ 57 public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; 58 /** {@hide} */ 59 public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; 60 /** {@hide} */ 61 public static final String priorityVarName = "priority"; 62 /** {@hide} */ 63 public static final String hiddenSSIDVarName = "scan_ssid"; 64 /** {@hide} */ 65 public static final String pmfVarName = "ieee80211w"; 66 /** {@hide} */ 67 public static final String updateIdentiferVarName = "update_identifier"; 68 /** {@hide} */ 69 public static final int INVALID_NETWORK_ID = -1; 70 /** {@hide} */ 71 public static final int LOCAL_ONLY_NETWORK_ID = -2; 72 73 /** {@hide} */ 74 private String mPasspointManagementObjectTree; 75 76 /** 77 * Recognized key management schemes. 78 */ 79 public static class KeyMgmt { KeyMgmt()80 private KeyMgmt() { } 81 82 /** WPA is not used; plaintext or static WEP could be used. */ 83 public static final int NONE = 0; 84 /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ 85 public static final int WPA_PSK = 1; 86 /** WPA using EAP authentication. Generally used with an external authentication server. */ 87 public static final int WPA_EAP = 2; 88 /** IEEE 802.1X using EAP authentication and (optionally) dynamically 89 * generated WEP keys. */ 90 public static final int IEEE8021X = 3; 91 92 /** WPA2 pre-shared key for use with soft access point 93 * (requires {@code preSharedKey} to be specified). 94 * @hide 95 */ 96 @SystemApi 97 public static final int WPA2_PSK = 4; 98 /** 99 * Hotspot 2.0 r2 OSEN: 100 * @hide 101 */ 102 public static final int OSEN = 5; 103 104 /** 105 * IEEE 802.11r Fast BSS Transition with PSK authentication. 106 * @hide 107 */ 108 public static final int FT_PSK = 6; 109 110 /** 111 * IEEE 802.11r Fast BSS Transition with EAP authentication. 112 * @hide 113 */ 114 public static final int FT_EAP = 7; 115 116 public static final String varName = "key_mgmt"; 117 118 public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", 119 "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" }; 120 } 121 122 /** 123 * Recognized security protocols. 124 */ 125 public static class Protocol { Protocol()126 private Protocol() { } 127 128 /** WPA/IEEE 802.11i/D3.0 */ 129 public static final int WPA = 0; 130 /** WPA2/IEEE 802.11i */ 131 public static final int RSN = 1; 132 /** HS2.0 r2 OSEN 133 * @hide 134 */ 135 public static final int OSEN = 2; 136 137 public static final String varName = "proto"; 138 139 public static final String[] strings = { "WPA", "RSN", "OSEN" }; 140 } 141 142 /** 143 * Recognized IEEE 802.11 authentication algorithms. 144 */ 145 public static class AuthAlgorithm { AuthAlgorithm()146 private AuthAlgorithm() { } 147 148 /** Open System authentication (required for WPA/WPA2) */ 149 public static final int OPEN = 0; 150 /** Shared Key authentication (requires static WEP keys) */ 151 public static final int SHARED = 1; 152 /** LEAP/Network EAP (only used with LEAP) */ 153 public static final int LEAP = 2; 154 155 public static final String varName = "auth_alg"; 156 157 public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; 158 } 159 160 /** 161 * Recognized pairwise ciphers for WPA. 162 */ 163 public static class PairwiseCipher { PairwiseCipher()164 private PairwiseCipher() { } 165 166 /** Use only Group keys (deprecated) */ 167 public static final int NONE = 0; 168 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 169 public static final int TKIP = 1; 170 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 171 public static final int CCMP = 2; 172 173 public static final String varName = "pairwise"; 174 175 public static final String[] strings = { "NONE", "TKIP", "CCMP" }; 176 } 177 178 /** 179 * Recognized group ciphers. 180 * <pre> 181 * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] 182 * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] 183 * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key 184 * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) 185 * </pre> 186 */ 187 public static class GroupCipher { GroupCipher()188 private GroupCipher() { } 189 190 /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */ 191 public static final int WEP40 = 0; 192 /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */ 193 public static final int WEP104 = 1; 194 /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ 195 public static final int TKIP = 2; 196 /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ 197 public static final int CCMP = 3; 198 /** Hotspot 2.0 r2 OSEN 199 * @hide 200 */ 201 public static final int GTK_NOT_USED = 4; 202 203 public static final String varName = "group"; 204 205 public static final String[] strings = 206 { "WEP40", "WEP104", "TKIP", "CCMP", "GTK_NOT_USED" }; 207 } 208 209 /** Possible status of a network configuration. */ 210 public static class Status { Status()211 private Status() { } 212 213 /** this is the network we are currently connected to */ 214 public static final int CURRENT = 0; 215 /** supplicant will not attempt to use this network */ 216 public static final int DISABLED = 1; 217 /** supplicant will consider this network available for association */ 218 public static final int ENABLED = 2; 219 220 public static final String[] strings = { "current", "disabled", "enabled" }; 221 } 222 223 /** @hide */ 224 public static final int UNKNOWN_UID = -1; 225 226 /** 227 * The ID number that the supplicant uses to identify this 228 * network configuration entry. This must be passed as an argument 229 * to most calls into the supplicant. 230 */ 231 public int networkId; 232 233 // Fixme We need remove this field to use only Quality network selection status only 234 /** 235 * The current status of this network configuration entry. 236 * @see Status 237 */ 238 public int status; 239 240 /** 241 * The network's SSID. Can either be an ASCII string, 242 * which must be enclosed in double quotation marks 243 * (e.g., {@code "MyNetwork"}), or a string of 244 * hex digits, which are not enclosed in quotes 245 * (e.g., {@code 01a243f405}). 246 */ 247 public String SSID; 248 /** 249 * When set, this network configuration entry should only be used when 250 * associating with the AP having the specified BSSID. The value is 251 * a string in the format of an Ethernet MAC address, e.g., 252 * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. 253 */ 254 public String BSSID; 255 256 /** 257 * 2GHz band. 258 * @hide 259 */ 260 public static final int AP_BAND_2GHZ = 0; 261 262 /** 263 * 5GHz band. 264 * @hide 265 */ 266 public static final int AP_BAND_5GHZ = 1; 267 268 /** 269 * The band which AP resides on 270 * 0-2G 1-5G 271 * By default, 2G is chosen 272 * @hide 273 */ 274 public int apBand = AP_BAND_2GHZ; 275 276 /** 277 * The channel which AP resides on,currently, US only 278 * 2G 1-11 279 * 5G 36,40,44,48,149,153,157,161,165 280 * 0 - find a random available channel according to the apBand 281 * @hide 282 */ 283 public int apChannel = 0; 284 285 /** 286 * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in 287 * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or 288 * a string of 64 hex digits for raw PSK. 289 * <p/> 290 * When the value of this key is read, the actual key is 291 * not returned, just a "*" if the key has a value, or the null 292 * string otherwise. 293 */ 294 public String preSharedKey; 295 296 /** 297 * Up to four WEP keys. Either an ASCII string enclosed in double 298 * quotation marks (e.g., {@code "abcdef"}) or a string 299 * of hex digits (e.g., {@code 0102030405}). 300 * <p/> 301 * When the value of one of these keys is read, the actual key is 302 * not returned, just a "*" if the key has a value, or the null 303 * string otherwise. 304 */ 305 public String[] wepKeys; 306 307 /** Default WEP key index, ranging from 0 to 3. */ 308 public int wepTxKeyIndex; 309 310 /** 311 * Priority determines the preference given to a network by {@code wpa_supplicant} 312 * when choosing an access point with which to associate. 313 * @deprecated This field does not exist anymore. 314 */ 315 @Deprecated 316 public int priority; 317 318 /** 319 * This is a network that does not broadcast its SSID, so an 320 * SSID-specific probe request must be used for scans. 321 */ 322 public boolean hiddenSSID; 323 324 /** 325 * This is a network that requries Protected Management Frames (PMF). 326 * @hide 327 */ 328 public boolean requirePMF; 329 330 /** 331 * Update identifier, for Passpoint network. 332 * @hide 333 */ 334 public String updateIdentifier; 335 336 /** 337 * The set of key management protocols supported by this configuration. 338 * See {@link KeyMgmt} for descriptions of the values. 339 * Defaults to WPA-PSK WPA-EAP. 340 */ 341 public BitSet allowedKeyManagement; 342 /** 343 * The set of security protocols supported by this configuration. 344 * See {@link Protocol} for descriptions of the values. 345 * Defaults to WPA RSN. 346 */ 347 public BitSet allowedProtocols; 348 /** 349 * The set of authentication protocols supported by this configuration. 350 * See {@link AuthAlgorithm} for descriptions of the values. 351 * Defaults to automatic selection. 352 */ 353 public BitSet allowedAuthAlgorithms; 354 /** 355 * The set of pairwise ciphers for WPA supported by this configuration. 356 * See {@link PairwiseCipher} for descriptions of the values. 357 * Defaults to CCMP TKIP. 358 */ 359 public BitSet allowedPairwiseCiphers; 360 /** 361 * The set of group ciphers supported by this configuration. 362 * See {@link GroupCipher} for descriptions of the values. 363 * Defaults to CCMP TKIP WEP104 WEP40. 364 */ 365 public BitSet allowedGroupCiphers; 366 /** 367 * The enterprise configuration details specifying the EAP method, 368 * certificates and other settings associated with the EAP. 369 */ 370 public WifiEnterpriseConfig enterpriseConfig; 371 372 /** 373 * Fully qualified domain name of a Passpoint configuration 374 */ 375 public String FQDN; 376 377 /** 378 * Name of Passpoint credential provider 379 */ 380 public String providerFriendlyName; 381 382 /** 383 * Flag indicating if this network is provided by a home Passpoint provider or a roaming 384 * Passpoint provider. This flag will be {@code true} if this network is provided by 385 * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider 386 * or is a non-Passpoint network. 387 */ 388 public boolean isHomeProviderNetwork; 389 390 /** 391 * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where 392 * Passpoint credential will be considered valid 393 */ 394 public long[] roamingConsortiumIds; 395 396 /** 397 * @hide 398 * This network configuration is visible to and usable by other users on the 399 * same device. 400 */ 401 public boolean shared; 402 403 /** 404 * @hide 405 */ 406 private IpConfiguration mIpConfiguration; 407 408 /** 409 * @hide 410 * dhcp server MAC address if known 411 */ 412 public String dhcpServer; 413 414 /** 415 * @hide 416 * default Gateway MAC address if known 417 */ 418 public String defaultGwMacAddress; 419 420 /** 421 * @hide 422 * last failure 423 */ 424 public String lastFailure; 425 426 /** 427 * @hide 428 * last time we connected, this configuration had validated internet access 429 */ 430 public boolean validatedInternetAccess; 431 432 /** 433 * @hide 434 * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM) 435 * This value is populated from scan results that contain Beacon Frames, which are infrequent. 436 * The value is not guaranteed to be set or current (Although it SHOULDNT change once set) 437 * Valid values are from 1 - 255. Initialized here as 0, use this to check if set. 438 */ 439 public int dtimInterval = 0; 440 441 /** 442 * Flag indicating if this configuration represents a legacy Passpoint configuration 443 * (Release N or older). This is used for migrating Passpoint configuration from N to O. 444 * This will no longer be needed after O. 445 * @hide 446 */ 447 public boolean isLegacyPasspointConfig = false; 448 /** 449 * @hide 450 * Uid of app creating the configuration 451 */ 452 @SystemApi 453 public int creatorUid; 454 455 /** 456 * @hide 457 * Uid of last app issuing a connection related command 458 */ 459 public int lastConnectUid; 460 461 /** 462 * @hide 463 * Uid of last app modifying the configuration 464 */ 465 @SystemApi 466 public int lastUpdateUid; 467 468 /** 469 * @hide 470 * Universal name for app creating the configuration 471 * see {#link {@link PackageManager#getNameForUid(int)} 472 */ 473 @SystemApi 474 public String creatorName; 475 476 /** 477 * @hide 478 * Universal name for app updating the configuration 479 * see {#link {@link PackageManager#getNameForUid(int)} 480 */ 481 @SystemApi 482 public String lastUpdateName; 483 484 /** 485 * @hide 486 * Status of user approval for connection 487 */ 488 public int userApproved = USER_UNSPECIFIED; 489 490 /** The Below RSSI thresholds are used to configure AutoJoin 491 * - GOOD/LOW/BAD thresholds are used so as to calculate link score 492 * - UNWANTED_SOFT are used by the blacklisting logic so as to handle 493 * the unwanted network message coming from CS 494 * - UNBLACKLIST thresholds are used so as to tweak the speed at which 495 * the network is unblacklisted (i.e. if 496 * it is seen with good RSSI, it is blacklisted faster) 497 * - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from 498 * the network we need to be before autojoin kicks in 499 */ 500 /** @hide **/ 501 public static int INVALID_RSSI = -127; 502 503 /** 504 * @hide 505 * A summary of the RSSI and Band status for that configuration 506 * This is used as a temporary value by the auto-join controller 507 */ 508 public static final class Visibility { 509 public int rssi5; // strongest 5GHz RSSI 510 public int rssi24; // strongest 2.4GHz RSSI 511 public int num5; // number of BSSIDs on 5GHz 512 public int num24; // number of BSSIDs on 2.4GHz 513 public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen) 514 public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen) 515 public String BSSID24; 516 public String BSSID5; 517 public int score; // Debug only, indicate last score used for autojoin/cell-handover 518 public int currentNetworkBoost; // Debug only, indicate boost applied to RSSI if current 519 public int bandPreferenceBoost; // Debug only, indicate boost applied to RSSI if current 520 public int lastChoiceBoost; // Debug only, indicate last choice applied to this configuration 521 public String lastChoiceConfig; // Debug only, indicate last choice applied to this configuration 522 Visibility()523 public Visibility() { 524 rssi5 = INVALID_RSSI; 525 rssi24 = INVALID_RSSI; 526 } 527 Visibility(Visibility source)528 public Visibility(Visibility source) { 529 rssi5 = source.rssi5; 530 rssi24 = source.rssi24; 531 age24 = source.age24; 532 age5 = source.age5; 533 num24 = source.num24; 534 num5 = source.num5; 535 BSSID5 = source.BSSID5; 536 BSSID24 = source.BSSID24; 537 } 538 539 @Override toString()540 public String toString() { 541 StringBuilder sbuf = new StringBuilder(); 542 sbuf.append("["); 543 if (rssi24 > INVALID_RSSI) { 544 sbuf.append(Integer.toString(rssi24)); 545 sbuf.append(","); 546 sbuf.append(Integer.toString(num24)); 547 if (BSSID24 != null) sbuf.append(",").append(BSSID24); 548 } 549 sbuf.append("; "); 550 if (rssi5 > INVALID_RSSI) { 551 sbuf.append(Integer.toString(rssi5)); 552 sbuf.append(","); 553 sbuf.append(Integer.toString(num5)); 554 if (BSSID5 != null) sbuf.append(",").append(BSSID5); 555 } 556 if (score != 0) { 557 sbuf.append("; ").append(score); 558 sbuf.append(", ").append(currentNetworkBoost); 559 sbuf.append(", ").append(bandPreferenceBoost); 560 if (lastChoiceConfig != null) { 561 sbuf.append(", ").append(lastChoiceBoost); 562 sbuf.append(", ").append(lastChoiceConfig); 563 } 564 } 565 sbuf.append("]"); 566 return sbuf.toString(); 567 } 568 } 569 570 /** @hide 571 * Cache the visibility status of this configuration. 572 * Visibility can change at any time depending on scan results availability. 573 * Owner of the WifiConfiguration is responsible to set this field based on 574 * recent scan results. 575 ***/ 576 public Visibility visibility; 577 578 /** @hide 579 * calculate and set Visibility for that configuration. 580 * 581 * age in milliseconds: we will consider only ScanResults that are more recent, 582 * i.e. younger. 583 ***/ setVisibility(Visibility status)584 public void setVisibility(Visibility status) { 585 visibility = status; 586 } 587 588 // States for the userApproved field 589 /** 590 * @hide 591 * User hasn't specified if connection is okay 592 */ 593 public static final int USER_UNSPECIFIED = 0; 594 /** 595 * @hide 596 * User has approved this for connection 597 */ 598 public static final int USER_APPROVED = 1; 599 /** 600 * @hide 601 * User has banned this from connection 602 */ 603 public static final int USER_BANNED = 2; 604 /** 605 * @hide 606 * Waiting for user input 607 */ 608 public static final int USER_PENDING = 3; 609 610 /** 611 * @hide 612 * Number of reports indicating no Internet Access 613 */ 614 public int numNoInternetAccessReports; 615 616 /** 617 * @hide 618 * For debug: date at which the config was last updated 619 */ 620 public String updateTime; 621 622 /** 623 * @hide 624 * For debug: date at which the config was last updated 625 */ 626 public String creationTime; 627 628 /** 629 * @hide 630 * The WiFi configuration is considered to have no internet access for purpose of autojoining 631 * if there has been a report of it having no internet access, and, it never have had 632 * internet access in the past. 633 */ 634 @SystemApi hasNoInternetAccess()635 public boolean hasNoInternetAccess() { 636 return numNoInternetAccessReports > 0 && !validatedInternetAccess; 637 } 638 639 /** 640 * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a 641 * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to 642 * this configuration and selects "don't ask again". 643 * @hide 644 */ 645 public boolean noInternetAccessExpected; 646 647 /** 648 * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a 649 * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to 650 * this configuration and selects "don't ask again". 651 * @hide 652 */ 653 @SystemApi isNoInternetAccessExpected()654 public boolean isNoInternetAccessExpected() { 655 return noInternetAccessExpected; 656 } 657 658 /** 659 * @hide 660 * Last time the system was connected to this configuration. 661 */ 662 public long lastConnected; 663 664 /** 665 * @hide 666 * Last time the system tried to connect and failed. 667 */ 668 public long lastConnectionFailure; 669 670 /** 671 * @hide 672 * Last time the system tried to roam and failed because of authentication failure or DHCP 673 * RENEW failure. 674 */ 675 public long lastRoamingFailure; 676 677 /** @hide */ 678 public static int ROAMING_FAILURE_IP_CONFIG = 1; 679 /** @hide */ 680 public static int ROAMING_FAILURE_AUTH_FAILURE = 2; 681 682 /** 683 * @hide 684 * Initial amount of time this Wifi configuration gets blacklisted for network switching 685 * because of roaming failure 686 */ 687 public long roamingFailureBlackListTimeMilli = 1000; 688 689 /** 690 * @hide 691 * Last roaming failure reason code 692 */ 693 public int lastRoamingFailureReason; 694 695 /** 696 * @hide 697 * Last time the system was disconnected to this configuration. 698 */ 699 public long lastDisconnected; 700 701 /** 702 * Set if the configuration was self added by the framework 703 * This boolean is cleared if we get a connect/save/ update or 704 * any wifiManager command that indicate the user interacted with the configuration 705 * since we will now consider that the configuration belong to him. 706 * @hide 707 */ 708 public boolean selfAdded; 709 710 /** 711 * Set if the configuration was self added by the framework 712 * This boolean is set once and never cleared. It is used 713 * so as we never loose track of who created the 714 * configuration in the first place. 715 * @hide 716 */ 717 public boolean didSelfAdd; 718 719 /** 720 * Peer WifiConfiguration this WifiConfiguration was added for 721 * @hide 722 */ 723 public String peerWifiConfiguration; 724 725 /** 726 * @hide 727 * Indicate that a WifiConfiguration is temporary and should not be saved 728 * nor considered by AutoJoin. 729 */ 730 public boolean ephemeral; 731 732 /** 733 * @hide 734 * Indicate that a WifiConfiguration is temporary and should not be saved 735 * nor considered by AutoJoin. 736 */ 737 @SystemApi isEphemeral()738 public boolean isEphemeral() { 739 return ephemeral; 740 } 741 742 /** 743 * @hide 744 * A hint about whether or not the network represented by this WifiConfiguration 745 * is metered. This is hinted at via the meteredHint bit on DHCP results set in 746 * {@link com.android.server.wifi.WifiStateMachine}, or via a network score in 747 * {@link com.android.server.wifi.ExternalScoreEvaluator}. 748 */ 749 @SystemApi 750 public boolean meteredHint; 751 752 /** 753 * @hide 754 * Indicates if a user has specified the WifiConfiguration to be metered. Users 755 * can toggle if a network is metered within Settings -> Data Usage -> Network 756 * Restrictions. 757 */ 758 public boolean meteredOverride; 759 760 /** 761 * @hide 762 * Setting this value will force scan results associated with this configuration to 763 * be included in the bucket of networks that are externally scored. 764 * If not set, associated scan results will be treated as legacy saved networks and 765 * will take precedence over networks in the scored category. 766 */ 767 @SystemApi 768 public boolean useExternalScores; 769 770 /** 771 * @hide 772 * Number of time the scorer overrode a the priority based choice, when comparing two 773 * WifiConfigurations, note that since comparing WifiConfiguration happens very often 774 * potentially at every scan, this number might become very large, even on an idle 775 * system. 776 */ 777 @SystemApi 778 public int numScorerOverride; 779 780 /** 781 * @hide 782 * Number of time the scorer overrode a the priority based choice, and the comparison 783 * triggered a network switch 784 */ 785 @SystemApi 786 public int numScorerOverrideAndSwitchedNetwork; 787 788 /** 789 * @hide 790 * Number of time we associated to this configuration. 791 */ 792 @SystemApi 793 public int numAssociation; 794 795 /** @hide 796 * Boost given to RSSI on a home network for the purpose of calculating the score 797 * This adds stickiness to home networks, as defined by: 798 * - less than 4 known BSSIDs 799 * - PSK only 800 * - TODO: add a test to verify that all BSSIDs are behind same gateway 801 ***/ 802 public static final int HOME_NETWORK_RSSI_BOOST = 5; 803 804 /** 805 * @hide 806 * This class is used to contain all the information and API used for quality network selection 807 */ 808 public static class NetworkSelectionStatus { 809 /** 810 * Quality Network Selection Status enable, temporary disabled, permanently disabled 811 */ 812 /** 813 * This network is allowed to join Quality Network Selection 814 */ 815 public static final int NETWORK_SELECTION_ENABLED = 0; 816 /** 817 * network was temporary disabled. Can be re-enabled after a time period expire 818 */ 819 public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; 820 /** 821 * network was permanently disabled. 822 */ 823 public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; 824 /** 825 * Maximum Network selection status 826 */ 827 public static final int NETWORK_SELECTION_STATUS_MAX = 3; 828 829 /** 830 * Quality network selection status String (for debug purpose). Use Quality network 831 * selection status value as index to extec the corresponding debug string 832 */ 833 public static final String[] QUALITY_NETWORK_SELECTION_STATUS = { 834 "NETWORK_SELECTION_ENABLED", 835 "NETWORK_SELECTION_TEMPORARY_DISABLED", 836 "NETWORK_SELECTION_PERMANENTLY_DISABLED"}; 837 838 //Quality Network disabled reasons 839 /** 840 * Default value. Means not disabled 841 */ 842 public static final int NETWORK_SELECTION_ENABLE = 0; 843 /** 844 * The starting index for network selection disabled reasons 845 */ 846 public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1; 847 /** 848 * @deprecated it is not used any more. 849 * This network is disabled because higher layer (>2) network is bad 850 */ 851 public static final int DISABLED_BAD_LINK = 1; 852 /** 853 * This network is disabled because multiple association rejects 854 */ 855 public static final int DISABLED_ASSOCIATION_REJECTION = 2; 856 /** 857 * This network is disabled because multiple authentication failure 858 */ 859 public static final int DISABLED_AUTHENTICATION_FAILURE = 3; 860 /** 861 * This network is disabled because multiple DHCP failure 862 */ 863 public static final int DISABLED_DHCP_FAILURE = 4; 864 /** 865 * This network is disabled because of security network but no credentials 866 */ 867 public static final int DISABLED_DNS_FAILURE = 5; 868 /** 869 * This network is disabled because we started WPS 870 */ 871 public static final int DISABLED_WPS_START = 6; 872 /** 873 * This network is disabled because EAP-TLS failure 874 */ 875 public static final int DISABLED_TLS_VERSION_MISMATCH = 7; 876 // Values above are for temporary disablement; values below are for permanent disablement. 877 /** 878 * This network is disabled due to absence of user credentials 879 */ 880 public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 8; 881 /** 882 * This network is disabled because no Internet connected and user do not want 883 */ 884 public static final int DISABLED_NO_INTERNET = 9; 885 /** 886 * This network is disabled due to WifiManager disable it explicitly 887 */ 888 public static final int DISABLED_BY_WIFI_MANAGER = 10; 889 /** 890 * This network is disabled due to user switching 891 */ 892 public static final int DISABLED_DUE_TO_USER_SWITCH = 11; 893 /** 894 * This Maximum disable reason value 895 */ 896 public static final int NETWORK_SELECTION_DISABLED_MAX = 12; 897 898 /** 899 * Quality network selection disable reason String (for debug purpose) 900 */ 901 public static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = { 902 "NETWORK_SELECTION_ENABLE", 903 "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated 904 "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ", 905 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE", 906 "NETWORK_SELECTION_DISABLED_DHCP_FAILURE", 907 "NETWORK_SELECTION_DISABLED_DNS_FAILURE", 908 "NETWORK_SELECTION_DISABLED_WPS_START", 909 "NETWORK_SELECTION_DISABLED_TLS_VERSION", 910 "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS", 911 "NETWORK_SELECTION_DISABLED_NO_INTERNET", 912 "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER", 913 "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH" 914 }; 915 916 /** 917 * Invalid time stamp for network selection disable 918 */ 919 public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L; 920 921 /** 922 * This constant indicates the current configuration has connect choice set 923 */ 924 private static final int CONNECT_CHOICE_EXISTS = 1; 925 926 /** 927 * This constant indicates the current configuration does not have connect choice set 928 */ 929 private static final int CONNECT_CHOICE_NOT_EXISTS = -1; 930 931 // fields for QualityNetwork Selection 932 /** 933 * Network selection status, should be in one of three status: enable, temporaily disabled 934 * or permanently disabled 935 */ 936 private int mStatus; 937 938 /** 939 * Reason for disable this network 940 */ 941 private int mNetworkSelectionDisableReason; 942 943 /** 944 * Last time we temporarily disabled the configuration 945 */ 946 private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 947 948 /** 949 * counter for each Network selection disable reason 950 */ 951 private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX]; 952 953 /** 954 * Connect Choice over this configuration 955 * 956 * When current wifi configuration is visible to the user but user explicitly choose to 957 * connect to another network X, the another networks X's configure key will be stored here. 958 * We will consider user has a preference of X over this network. And in the future, 959 * network selection will always give X a higher preference over this configuration. 960 * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP 961 */ 962 private String mConnectChoice; 963 964 /** 965 * The system timestamp when we records the connectChoice. This value is obtained from 966 * System.currentTimeMillis 967 */ 968 private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 969 970 /** 971 * Used to cache the temporary candidate during the network selection procedure. It will be 972 * kept updating once a new scan result has a higher score than current one 973 */ 974 private ScanResult mCandidate; 975 976 /** 977 * Used to cache the score of the current temporary candidate during the network 978 * selection procedure. 979 */ 980 private int mCandidateScore; 981 982 /** 983 * Indicate whether this network is visible in latest Qualified Network Selection. This 984 * means there is scan result found related to this Configuration and meet the minimum 985 * requirement. The saved network need not join latest Qualified Network Selection. For 986 * example, it is disabled. True means network is visible in latest Qualified Network 987 * Selection and false means network is invisible 988 */ 989 private boolean mSeenInLastQualifiedNetworkSelection; 990 991 /** 992 * Boolean indicating if we have ever successfully connected to this network. 993 * 994 * This value will be set to true upon a successful connection. 995 * This value will be set to false if a previous value was not stored in the config or if 996 * the credentials are updated (ex. a password change). 997 */ 998 private boolean mHasEverConnected; 999 1000 /** 1001 * Boolean indicating whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} 1002 * chose not to connect to this network in the last qualified network selection process. 1003 */ 1004 private boolean mNotRecommended; 1005 1006 /** 1007 * Set whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not 1008 * recommend connecting to this network. 1009 */ setNotRecommended(boolean notRecommended)1010 public void setNotRecommended(boolean notRecommended) { 1011 mNotRecommended = notRecommended; 1012 } 1013 1014 /** 1015 * Returns whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not 1016 * recommend connecting to this network. 1017 */ isNotRecommended()1018 public boolean isNotRecommended() { 1019 return mNotRecommended; 1020 } 1021 1022 /** 1023 * set whether this network is visible in latest Qualified Network Selection 1024 * @param seen value set to candidate 1025 */ setSeenInLastQualifiedNetworkSelection(boolean seen)1026 public void setSeenInLastQualifiedNetworkSelection(boolean seen) { 1027 mSeenInLastQualifiedNetworkSelection = seen; 1028 } 1029 1030 /** 1031 * get whether this network is visible in latest Qualified Network Selection 1032 * @return returns true -- network is visible in latest Qualified Network Selection 1033 * false -- network is invisible in latest Qualified Network Selection 1034 */ getSeenInLastQualifiedNetworkSelection()1035 public boolean getSeenInLastQualifiedNetworkSelection() { 1036 return mSeenInLastQualifiedNetworkSelection; 1037 } 1038 /** 1039 * set the temporary candidate of current network selection procedure 1040 * @param scanCandidate {@link ScanResult} the candidate set to mCandidate 1041 */ setCandidate(ScanResult scanCandidate)1042 public void setCandidate(ScanResult scanCandidate) { 1043 mCandidate = scanCandidate; 1044 } 1045 1046 /** 1047 * get the temporary candidate of current network selection procedure 1048 * @return returns {@link ScanResult} temporary candidate of current network selection 1049 * procedure 1050 */ getCandidate()1051 public ScanResult getCandidate() { 1052 return mCandidate; 1053 } 1054 1055 /** 1056 * set the score of the temporary candidate of current network selection procedure 1057 * @param score value set to mCandidateScore 1058 */ setCandidateScore(int score)1059 public void setCandidateScore(int score) { 1060 mCandidateScore = score; 1061 } 1062 1063 /** 1064 * get the score of the temporary candidate of current network selection procedure 1065 * @return returns score of the temporary candidate of current network selection procedure 1066 */ getCandidateScore()1067 public int getCandidateScore() { 1068 return mCandidateScore; 1069 } 1070 1071 /** 1072 * get user preferred choice over this configuration 1073 *@return returns configKey of user preferred choice over this configuration 1074 */ getConnectChoice()1075 public String getConnectChoice() { 1076 return mConnectChoice; 1077 } 1078 1079 /** 1080 * set user preferred choice over this configuration 1081 * @param newConnectChoice, the configKey of user preferred choice over this configuration 1082 */ setConnectChoice(String newConnectChoice)1083 public void setConnectChoice(String newConnectChoice) { 1084 mConnectChoice = newConnectChoice; 1085 } 1086 1087 /** 1088 * get the timeStamp when user select a choice over this configuration 1089 * @return returns when current connectChoice is set (time from System.currentTimeMillis) 1090 */ getConnectChoiceTimestamp()1091 public long getConnectChoiceTimestamp() { 1092 return mConnectChoiceTimestamp; 1093 } 1094 1095 /** 1096 * set the timeStamp when user select a choice over this configuration 1097 * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should 1098 * be obtained from System.currentTimeMillis 1099 */ setConnectChoiceTimestamp(long timeStamp)1100 public void setConnectChoiceTimestamp(long timeStamp) { 1101 mConnectChoiceTimestamp = timeStamp; 1102 } 1103 1104 /** 1105 * get current Quality network selection status 1106 * @return returns current Quality network selection status in String (for debug purpose) 1107 */ getNetworkStatusString()1108 public String getNetworkStatusString() { 1109 return QUALITY_NETWORK_SELECTION_STATUS[mStatus]; 1110 } 1111 setHasEverConnected(boolean value)1112 public void setHasEverConnected(boolean value) { 1113 mHasEverConnected = value; 1114 } 1115 getHasEverConnected()1116 public boolean getHasEverConnected() { 1117 return mHasEverConnected; 1118 } 1119 NetworkSelectionStatus()1120 public NetworkSelectionStatus() { 1121 // previously stored configs will not have this parameter, so we default to false. 1122 mHasEverConnected = false; 1123 }; 1124 1125 /** 1126 * @param reason specific error reason 1127 * @return corresponding network disable reason String (for debug purpose) 1128 */ getNetworkDisableReasonString(int reason)1129 public static String getNetworkDisableReasonString(int reason) { 1130 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1131 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[reason]; 1132 } else { 1133 return null; 1134 } 1135 } 1136 /** 1137 * get current network disable reason 1138 * @return current network disable reason in String (for debug purpose) 1139 */ getNetworkDisableReasonString()1140 public String getNetworkDisableReasonString() { 1141 return QUALITY_NETWORK_SELECTION_DISABLE_REASON[mNetworkSelectionDisableReason]; 1142 } 1143 1144 /** 1145 * get current network network selection status 1146 * @return return current network network selection status 1147 */ getNetworkSelectionStatus()1148 public int getNetworkSelectionStatus() { 1149 return mStatus; 1150 } 1151 /** 1152 * @return whether current network is enabled to join network selection 1153 */ isNetworkEnabled()1154 public boolean isNetworkEnabled() { 1155 return mStatus == NETWORK_SELECTION_ENABLED; 1156 } 1157 1158 /** 1159 * @return whether current network is temporary disabled 1160 */ isNetworkTemporaryDisabled()1161 public boolean isNetworkTemporaryDisabled() { 1162 return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED; 1163 } 1164 1165 /** 1166 * @return returns whether current network is permanently disabled 1167 */ isNetworkPermanentlyDisabled()1168 public boolean isNetworkPermanentlyDisabled() { 1169 return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED; 1170 } 1171 1172 /** 1173 * set current networ work selection status 1174 * @param status network selection status to set 1175 */ setNetworkSelectionStatus(int status)1176 public void setNetworkSelectionStatus(int status) { 1177 if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) { 1178 mStatus = status; 1179 } 1180 } 1181 1182 /** 1183 * @return returns current network's disable reason 1184 */ getNetworkSelectionDisableReason()1185 public int getNetworkSelectionDisableReason() { 1186 return mNetworkSelectionDisableReason; 1187 } 1188 1189 /** 1190 * set Network disable reason 1191 * @param reason Network disable reason 1192 */ setNetworkSelectionDisableReason(int reason)1193 public void setNetworkSelectionDisableReason(int reason) { 1194 if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) { 1195 mNetworkSelectionDisableReason = reason; 1196 } else { 1197 throw new IllegalArgumentException("Illegal reason value: " + reason); 1198 } 1199 } 1200 1201 /** 1202 * check whether network is disabled by this reason 1203 * @param reason a specific disable reason 1204 * @return true -- network is disabled for this reason 1205 * false -- network is not disabled for this reason 1206 */ isDisabledByReason(int reason)1207 public boolean isDisabledByReason(int reason) { 1208 return mNetworkSelectionDisableReason == reason; 1209 } 1210 1211 /** 1212 * @param timeStamp Set when current network is disabled in millisecond since January 1, 1213 * 1970 00:00:00.0 UTC 1214 */ setDisableTime(long timeStamp)1215 public void setDisableTime(long timeStamp) { 1216 mTemporarilyDisabledTimestamp = timeStamp; 1217 } 1218 1219 /** 1220 * @return returns when current network is disabled in millisecond since January 1, 1221 * 1970 00:00:00.0 UTC 1222 */ getDisableTime()1223 public long getDisableTime() { 1224 return mTemporarilyDisabledTimestamp; 1225 } 1226 1227 /** 1228 * get the disable counter of a specific reason 1229 * @param reason specific failure reason 1230 * @exception throw IllegalArgumentException for illegal input 1231 * @return counter number for specific error reason. 1232 */ getDisableReasonCounter(int reason)1233 public int getDisableReasonCounter(int reason) { 1234 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1235 return mNetworkSeclectionDisableCounter[reason]; 1236 } else { 1237 throw new IllegalArgumentException("Illegal reason value: " + reason); 1238 } 1239 } 1240 1241 /** 1242 * set the counter of a specific failure reason 1243 * @param reason reason for disable error 1244 * @param value the counter value for this specific reason 1245 * @exception throw IllegalArgumentException for illegal input 1246 */ setDisableReasonCounter(int reason, int value)1247 public void setDisableReasonCounter(int reason, int value) { 1248 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1249 mNetworkSeclectionDisableCounter[reason] = value; 1250 } else { 1251 throw new IllegalArgumentException("Illegal reason value: " + reason); 1252 } 1253 } 1254 1255 /** 1256 * increment the counter of a specific failure reason 1257 * @param reason a specific failure reason 1258 * @exception throw IllegalArgumentException for illegal input 1259 */ incrementDisableReasonCounter(int reason)1260 public void incrementDisableReasonCounter(int reason) { 1261 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1262 mNetworkSeclectionDisableCounter[reason]++; 1263 } else { 1264 throw new IllegalArgumentException("Illegal reason value: " + reason); 1265 } 1266 } 1267 1268 /** 1269 * clear the counter of a specific failure reason 1270 * @hide 1271 * @param reason a specific failure reason 1272 * @exception throw IllegalArgumentException for illegal input 1273 */ clearDisableReasonCounter(int reason)1274 public void clearDisableReasonCounter(int reason) { 1275 if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { 1276 mNetworkSeclectionDisableCounter[reason] = NETWORK_SELECTION_ENABLE; 1277 } else { 1278 throw new IllegalArgumentException("Illegal reason value: " + reason); 1279 } 1280 } 1281 1282 /** 1283 * clear all the failure reason counters 1284 */ clearDisableReasonCounter()1285 public void clearDisableReasonCounter() { 1286 Arrays.fill(mNetworkSeclectionDisableCounter, NETWORK_SELECTION_ENABLE); 1287 } 1288 1289 /** 1290 * BSSID for connection to this network (through network selection procedure) 1291 */ 1292 private String mNetworkSelectionBSSID; 1293 1294 /** 1295 * get current network Selection BSSID 1296 * @return current network Selection BSSID 1297 */ getNetworkSelectionBSSID()1298 public String getNetworkSelectionBSSID() { 1299 return mNetworkSelectionBSSID; 1300 } 1301 1302 /** 1303 * set network Selection BSSID 1304 * @param bssid The target BSSID for assocaition 1305 */ setNetworkSelectionBSSID(String bssid)1306 public void setNetworkSelectionBSSID(String bssid) { 1307 mNetworkSelectionBSSID = bssid; 1308 } 1309 copy(NetworkSelectionStatus source)1310 public void copy(NetworkSelectionStatus source) { 1311 mStatus = source.mStatus; 1312 mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason; 1313 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1314 index++) { 1315 mNetworkSeclectionDisableCounter[index] = 1316 source.mNetworkSeclectionDisableCounter[index]; 1317 } 1318 mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp; 1319 mNetworkSelectionBSSID = source.mNetworkSelectionBSSID; 1320 setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection()); 1321 setCandidate(source.getCandidate()); 1322 setCandidateScore(source.getCandidateScore()); 1323 setConnectChoice(source.getConnectChoice()); 1324 setConnectChoiceTimestamp(source.getConnectChoiceTimestamp()); 1325 setHasEverConnected(source.getHasEverConnected()); 1326 setNotRecommended(source.isNotRecommended()); 1327 } 1328 writeToParcel(Parcel dest)1329 public void writeToParcel(Parcel dest) { 1330 dest.writeInt(getNetworkSelectionStatus()); 1331 dest.writeInt(getNetworkSelectionDisableReason()); 1332 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1333 index++) { 1334 dest.writeInt(getDisableReasonCounter(index)); 1335 } 1336 dest.writeLong(getDisableTime()); 1337 dest.writeString(getNetworkSelectionBSSID()); 1338 if (getConnectChoice() != null) { 1339 dest.writeInt(CONNECT_CHOICE_EXISTS); 1340 dest.writeString(getConnectChoice()); 1341 dest.writeLong(getConnectChoiceTimestamp()); 1342 } else { 1343 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); 1344 } 1345 dest.writeInt(getHasEverConnected() ? 1 : 0); 1346 dest.writeInt(isNotRecommended() ? 1 : 0); 1347 } 1348 readFromParcel(Parcel in)1349 public void readFromParcel(Parcel in) { 1350 setNetworkSelectionStatus(in.readInt()); 1351 setNetworkSelectionDisableReason(in.readInt()); 1352 for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; 1353 index++) { 1354 setDisableReasonCounter(index, in.readInt()); 1355 } 1356 setDisableTime(in.readLong()); 1357 setNetworkSelectionBSSID(in.readString()); 1358 if (in.readInt() == CONNECT_CHOICE_EXISTS) { 1359 setConnectChoice(in.readString()); 1360 setConnectChoiceTimestamp(in.readLong()); 1361 } else { 1362 setConnectChoice(null); 1363 setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); 1364 } 1365 setHasEverConnected(in.readInt() != 0); 1366 setNotRecommended(in.readInt() != 0); 1367 } 1368 } 1369 1370 /** 1371 * @hide 1372 * network selection related member 1373 */ 1374 private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus(); 1375 1376 /** 1377 * @hide 1378 * @return network selection status 1379 */ getNetworkSelectionStatus()1380 public NetworkSelectionStatus getNetworkSelectionStatus() { 1381 return mNetworkSelectionStatus; 1382 } 1383 1384 /** 1385 * Set the network selection status 1386 * @hide 1387 */ setNetworkSelectionStatus(NetworkSelectionStatus status)1388 public void setNetworkSelectionStatus(NetworkSelectionStatus status) { 1389 mNetworkSelectionStatus = status; 1390 } 1391 1392 /** 1393 * @hide 1394 * Linked Configurations: represent the set of Wificonfigurations that are equivalent 1395 * regarding roaming and auto-joining. 1396 * The linked configuration may or may not have same SSID, and may or may not have same 1397 * credentials. 1398 * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. 1399 */ 1400 public HashMap<String, Integer> linkedConfigurations; 1401 WifiConfiguration()1402 public WifiConfiguration() { 1403 networkId = INVALID_NETWORK_ID; 1404 SSID = null; 1405 BSSID = null; 1406 FQDN = null; 1407 roamingConsortiumIds = new long[0]; 1408 priority = 0; 1409 hiddenSSID = false; 1410 allowedKeyManagement = new BitSet(); 1411 allowedProtocols = new BitSet(); 1412 allowedAuthAlgorithms = new BitSet(); 1413 allowedPairwiseCiphers = new BitSet(); 1414 allowedGroupCiphers = new BitSet(); 1415 wepKeys = new String[4]; 1416 for (int i = 0; i < wepKeys.length; i++) { 1417 wepKeys[i] = null; 1418 } 1419 enterpriseConfig = new WifiEnterpriseConfig(); 1420 selfAdded = false; 1421 didSelfAdd = false; 1422 ephemeral = false; 1423 meteredHint = false; 1424 meteredOverride = false; 1425 useExternalScores = false; 1426 validatedInternetAccess = false; 1427 mIpConfiguration = new IpConfiguration(); 1428 lastUpdateUid = -1; 1429 creatorUid = -1; 1430 shared = true; 1431 dtimInterval = 0; 1432 } 1433 1434 /** 1435 * Identify if this configuration represents a Passpoint network 1436 */ isPasspoint()1437 public boolean isPasspoint() { 1438 return !TextUtils.isEmpty(FQDN) 1439 && !TextUtils.isEmpty(providerFriendlyName) 1440 && enterpriseConfig != null 1441 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 1442 } 1443 1444 /** 1445 * Helper function, identify if a configuration is linked 1446 * @hide 1447 */ isLinked(WifiConfiguration config)1448 public boolean isLinked(WifiConfiguration config) { 1449 if (config != null) { 1450 if (config.linkedConfigurations != null && linkedConfigurations != null) { 1451 if (config.linkedConfigurations.get(configKey()) != null 1452 && linkedConfigurations.get(config.configKey()) != null) { 1453 return true; 1454 } 1455 } 1456 } 1457 return false; 1458 } 1459 1460 /** 1461 * Helper function, idenfity if a configuration should be treated as an enterprise network 1462 * @hide 1463 */ isEnterprise()1464 public boolean isEnterprise() { 1465 return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) 1466 || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) 1467 && enterpriseConfig != null 1468 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; 1469 } 1470 1471 @Override toString()1472 public String toString() { 1473 StringBuilder sbuf = new StringBuilder(); 1474 if (this.status == WifiConfiguration.Status.CURRENT) { 1475 sbuf.append("* "); 1476 } else if (this.status == WifiConfiguration.Status.DISABLED) { 1477 sbuf.append("- DSBLE "); 1478 } 1479 sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). 1480 append(" PROVIDER-NAME: ").append(this.providerFriendlyName). 1481 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN) 1482 .append(" PRIO: ").append(this.priority) 1483 .append(" HIDDEN: ").append(this.hiddenSSID) 1484 .append('\n'); 1485 1486 1487 sbuf.append(" NetworkSelectionStatus ") 1488 .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n"); 1489 if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) { 1490 sbuf.append(" mNetworkSelectionDisableReason ") 1491 .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n"); 1492 1493 for (int index = mNetworkSelectionStatus.NETWORK_SELECTION_ENABLE; 1494 index < mNetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) { 1495 if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) { 1496 sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index) 1497 + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index) 1498 + "\n"); 1499 } 1500 } 1501 } 1502 if (mNetworkSelectionStatus.getConnectChoice() != null) { 1503 sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); 1504 sbuf.append(" connect choice set time: ").append(mNetworkSelectionStatus 1505 .getConnectChoiceTimestamp()); 1506 } 1507 sbuf.append(" hasEverConnected: ") 1508 .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n"); 1509 1510 if (this.numAssociation > 0) { 1511 sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); 1512 } 1513 if (this.numNoInternetAccessReports > 0) { 1514 sbuf.append(" numNoInternetAccessReports "); 1515 sbuf.append(this.numNoInternetAccessReports).append("\n"); 1516 } 1517 if (this.updateTime != null) { 1518 sbuf.append("update ").append(this.updateTime).append("\n"); 1519 } 1520 if (this.creationTime != null) { 1521 sbuf.append("creation").append(this.creationTime).append("\n"); 1522 } 1523 if (this.didSelfAdd) sbuf.append(" didSelfAdd"); 1524 if (this.selfAdded) sbuf.append(" selfAdded"); 1525 if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); 1526 if (this.ephemeral) sbuf.append(" ephemeral"); 1527 if (this.meteredHint) sbuf.append(" meteredHint"); 1528 if (this.meteredOverride) sbuf.append(" meteredOverride"); 1529 if (this.useExternalScores) sbuf.append(" useExternalScores"); 1530 if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess 1531 || this.ephemeral || this.meteredHint || this.meteredOverride 1532 || this.useExternalScores) { 1533 sbuf.append("\n"); 1534 } 1535 sbuf.append(" KeyMgmt:"); 1536 for (int k = 0; k < this.allowedKeyManagement.size(); k++) { 1537 if (this.allowedKeyManagement.get(k)) { 1538 sbuf.append(" "); 1539 if (k < KeyMgmt.strings.length) { 1540 sbuf.append(KeyMgmt.strings[k]); 1541 } else { 1542 sbuf.append("??"); 1543 } 1544 } 1545 } 1546 sbuf.append(" Protocols:"); 1547 for (int p = 0; p < this.allowedProtocols.size(); p++) { 1548 if (this.allowedProtocols.get(p)) { 1549 sbuf.append(" "); 1550 if (p < Protocol.strings.length) { 1551 sbuf.append(Protocol.strings[p]); 1552 } else { 1553 sbuf.append("??"); 1554 } 1555 } 1556 } 1557 sbuf.append('\n'); 1558 sbuf.append(" AuthAlgorithms:"); 1559 for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { 1560 if (this.allowedAuthAlgorithms.get(a)) { 1561 sbuf.append(" "); 1562 if (a < AuthAlgorithm.strings.length) { 1563 sbuf.append(AuthAlgorithm.strings[a]); 1564 } else { 1565 sbuf.append("??"); 1566 } 1567 } 1568 } 1569 sbuf.append('\n'); 1570 sbuf.append(" PairwiseCiphers:"); 1571 for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { 1572 if (this.allowedPairwiseCiphers.get(pc)) { 1573 sbuf.append(" "); 1574 if (pc < PairwiseCipher.strings.length) { 1575 sbuf.append(PairwiseCipher.strings[pc]); 1576 } else { 1577 sbuf.append("??"); 1578 } 1579 } 1580 } 1581 sbuf.append('\n'); 1582 sbuf.append(" GroupCiphers:"); 1583 for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { 1584 if (this.allowedGroupCiphers.get(gc)) { 1585 sbuf.append(" "); 1586 if (gc < GroupCipher.strings.length) { 1587 sbuf.append(GroupCipher.strings[gc]); 1588 } else { 1589 sbuf.append("??"); 1590 } 1591 } 1592 } 1593 sbuf.append('\n').append(" PSK: "); 1594 if (this.preSharedKey != null) { 1595 sbuf.append('*'); 1596 } 1597 sbuf.append("\nEnterprise config:\n"); 1598 sbuf.append(enterpriseConfig); 1599 1600 sbuf.append("IP config:\n"); 1601 sbuf.append(mIpConfiguration.toString()); 1602 1603 if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) { 1604 sbuf.append(" networkSelectionBSSID=" 1605 + mNetworkSelectionStatus.getNetworkSelectionBSSID()); 1606 } 1607 long now_ms = System.currentTimeMillis(); 1608 if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus 1609 .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) { 1610 sbuf.append('\n'); 1611 long diff = now_ms - mNetworkSelectionStatus.getDisableTime(); 1612 if (diff <= 0) { 1613 sbuf.append(" blackListed since <incorrect>"); 1614 } else { 1615 sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec "); 1616 } 1617 } 1618 if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid); 1619 if (creatorName != null) sbuf.append(" cname=" + creatorName); 1620 if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid); 1621 if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName); 1622 sbuf.append(" lcuid=" + lastConnectUid); 1623 sbuf.append(" userApproved=" + userApprovedAsString(userApproved)); 1624 sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected); 1625 sbuf.append(" "); 1626 1627 if (this.lastConnected != 0) { 1628 sbuf.append('\n'); 1629 long diff = now_ms - this.lastConnected; 1630 if (diff <= 0) { 1631 sbuf.append("lastConnected since <incorrect>"); 1632 } else { 1633 sbuf.append("lastConnected: ").append(Long.toString(diff / 1000)).append("sec "); 1634 } 1635 } 1636 if (this.lastConnectionFailure != 0) { 1637 sbuf.append('\n'); 1638 long diff = now_ms - this.lastConnectionFailure; 1639 if (diff <= 0) { 1640 sbuf.append("lastConnectionFailure since <incorrect> "); 1641 } else { 1642 sbuf.append("lastConnectionFailure: ").append(Long.toString(diff / 1000)); 1643 sbuf.append("sec "); 1644 } 1645 } 1646 if (this.lastRoamingFailure != 0) { 1647 sbuf.append('\n'); 1648 long diff = now_ms - this.lastRoamingFailure; 1649 if (diff <= 0) { 1650 sbuf.append("lastRoamingFailure since <incorrect> "); 1651 } else { 1652 sbuf.append("lastRoamingFailure: ").append(Long.toString(diff / 1000)); 1653 sbuf.append("sec "); 1654 } 1655 } 1656 sbuf.append("roamingFailureBlackListTimeMilli: "). 1657 append(Long.toString(this.roamingFailureBlackListTimeMilli)); 1658 sbuf.append('\n'); 1659 if (this.linkedConfigurations != null) { 1660 for (String key : this.linkedConfigurations.keySet()) { 1661 sbuf.append(" linked: ").append(key); 1662 sbuf.append('\n'); 1663 } 1664 } 1665 1666 return sbuf.toString(); 1667 } 1668 1669 /** {@hide} */ getPrintableSsid()1670 public String getPrintableSsid() { 1671 if (SSID == null) return ""; 1672 final int length = SSID.length(); 1673 if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { 1674 return SSID.substring(1, length - 1); 1675 } 1676 1677 /** The ascii-encoded string format is P"<ascii-encoded-string>" 1678 * The decoding is implemented in the supplicant for a newly configured 1679 * network. 1680 */ 1681 if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && 1682 (SSID.charAt(length-1) == '"')) { 1683 WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( 1684 SSID.substring(2, length - 1)); 1685 return wifiSsid.toString(); 1686 } 1687 return SSID; 1688 } 1689 1690 /** @hide **/ userApprovedAsString(int userApproved)1691 public static String userApprovedAsString(int userApproved) { 1692 switch (userApproved) { 1693 case USER_APPROVED: 1694 return "USER_APPROVED"; 1695 case USER_BANNED: 1696 return "USER_BANNED"; 1697 case USER_UNSPECIFIED: 1698 return "USER_UNSPECIFIED"; 1699 default: 1700 return "INVALID"; 1701 } 1702 } 1703 1704 /** 1705 * Get an identifier for associating credentials with this config 1706 * @param current configuration contains values for additional fields 1707 * that are not part of this configuration. Used 1708 * when a config with some fields is passed by an application. 1709 * @throws IllegalStateException if config is invalid for key id generation 1710 * @hide 1711 */ getKeyIdForCredentials(WifiConfiguration current)1712 public String getKeyIdForCredentials(WifiConfiguration current) { 1713 String keyMgmt = null; 1714 1715 try { 1716 // Get current config details for fields that are not initialized 1717 if (TextUtils.isEmpty(SSID)) SSID = current.SSID; 1718 if (allowedKeyManagement.cardinality() == 0) { 1719 allowedKeyManagement = current.allowedKeyManagement; 1720 } 1721 if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1722 keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1723 } 1724 if (allowedKeyManagement.get(KeyMgmt.OSEN)) { 1725 keyMgmt = KeyMgmt.strings[KeyMgmt.OSEN]; 1726 } 1727 if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1728 keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; 1729 } 1730 1731 if (TextUtils.isEmpty(keyMgmt)) { 1732 throw new IllegalStateException("Not an EAP network"); 1733 } 1734 1735 return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + 1736 trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? 1737 current.enterpriseConfig : null)); 1738 } catch (NullPointerException e) { 1739 throw new IllegalStateException("Invalid config details"); 1740 } 1741 } 1742 trimStringForKeyId(String string)1743 private String trimStringForKeyId(String string) { 1744 // Remove quotes and spaces 1745 return string.replace("\"", "").replace(" ", ""); 1746 } 1747 readBitSet(Parcel src)1748 private static BitSet readBitSet(Parcel src) { 1749 int cardinality = src.readInt(); 1750 1751 BitSet set = new BitSet(); 1752 for (int i = 0; i < cardinality; i++) { 1753 set.set(src.readInt()); 1754 } 1755 1756 return set; 1757 } 1758 writeBitSet(Parcel dest, BitSet set)1759 private static void writeBitSet(Parcel dest, BitSet set) { 1760 int nextSetBit = -1; 1761 1762 dest.writeInt(set.cardinality()); 1763 1764 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1765 dest.writeInt(nextSetBit); 1766 } 1767 } 1768 1769 /** @hide */ getAuthType()1770 public int getAuthType() { 1771 if (allowedKeyManagement.cardinality() > 1) { 1772 throw new IllegalStateException("More than one auth type set"); 1773 } 1774 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1775 return KeyMgmt.WPA_PSK; 1776 } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { 1777 return KeyMgmt.WPA2_PSK; 1778 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { 1779 return KeyMgmt.WPA_EAP; 1780 } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1781 return KeyMgmt.IEEE8021X; 1782 } 1783 return KeyMgmt.NONE; 1784 } 1785 1786 /* @hide 1787 * Cache the config key, this seems useful as a speed up since a lot of 1788 * lookups in the config store are done and based on this key. 1789 */ 1790 String mCachedConfigKey; 1791 1792 /** @hide 1793 * return the string used to calculate the hash in WifiConfigStore 1794 * and uniquely identify this WifiConfiguration 1795 */ configKey(boolean allowCached)1796 public String configKey(boolean allowCached) { 1797 String key; 1798 if (allowCached && mCachedConfigKey != null) { 1799 key = mCachedConfigKey; 1800 } else if (providerFriendlyName != null) { 1801 key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1802 if (!shared) { 1803 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); 1804 } 1805 } else { 1806 if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1807 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1808 } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1809 allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1810 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1811 } else if (wepKeys[0] != null) { 1812 key = SSID + "WEP"; 1813 } else { 1814 key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1815 } 1816 if (!shared) { 1817 key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); 1818 } 1819 mCachedConfigKey = key; 1820 } 1821 return key; 1822 } 1823 1824 /** @hide 1825 * get configKey, force calculating the config string 1826 */ configKey()1827 public String configKey() { 1828 return configKey(false); 1829 } 1830 1831 /** @hide */ getIpConfiguration()1832 public IpConfiguration getIpConfiguration() { 1833 return mIpConfiguration; 1834 } 1835 1836 /** @hide */ setIpConfiguration(IpConfiguration ipConfiguration)1837 public void setIpConfiguration(IpConfiguration ipConfiguration) { 1838 mIpConfiguration = ipConfiguration; 1839 } 1840 1841 /** @hide */ getStaticIpConfiguration()1842 public StaticIpConfiguration getStaticIpConfiguration() { 1843 return mIpConfiguration.getStaticIpConfiguration(); 1844 } 1845 1846 /** @hide */ setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)1847 public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { 1848 mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); 1849 } 1850 1851 /** @hide */ getIpAssignment()1852 public IpConfiguration.IpAssignment getIpAssignment() { 1853 return mIpConfiguration.ipAssignment; 1854 } 1855 1856 /** @hide */ setIpAssignment(IpConfiguration.IpAssignment ipAssignment)1857 public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { 1858 mIpConfiguration.ipAssignment = ipAssignment; 1859 } 1860 1861 /** @hide */ getProxySettings()1862 public IpConfiguration.ProxySettings getProxySettings() { 1863 return mIpConfiguration.proxySettings; 1864 } 1865 1866 /** @hide */ setProxySettings(IpConfiguration.ProxySettings proxySettings)1867 public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { 1868 mIpConfiguration.proxySettings = proxySettings; 1869 } 1870 1871 /** 1872 * Returns the HTTP proxy used by this object. 1873 * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this 1874 * WifiConfiguration, or {@code null} if no proxy is specified. 1875 */ getHttpProxy()1876 public ProxyInfo getHttpProxy() { 1877 if (mIpConfiguration.proxySettings == IpConfiguration.ProxySettings.NONE) { 1878 return null; 1879 } 1880 return new ProxyInfo(mIpConfiguration.httpProxy); 1881 } 1882 1883 /** 1884 * Set the {@link ProxyInfo} for this WifiConfiguration. 1885 * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this 1886 * WifiConfiguration. Setting this {@code null} will explicitly set no proxy, 1887 * removing any proxy that was previously set. 1888 * @exception throw IllegalArgumentException for invalid httpProxy 1889 */ setHttpProxy(ProxyInfo httpProxy)1890 public void setHttpProxy(ProxyInfo httpProxy) { 1891 if (httpProxy == null) { 1892 mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); 1893 mIpConfiguration.setHttpProxy(null); 1894 return; 1895 } 1896 ProxyInfo httpProxyCopy; 1897 ProxySettings proxySettingCopy; 1898 if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) { 1899 proxySettingCopy = IpConfiguration.ProxySettings.PAC; 1900 // Construct a new PAC URL Proxy 1901 httpProxyCopy = new ProxyInfo(httpProxy.getPacFileUrl(), httpProxy.getPort()); 1902 } else { 1903 proxySettingCopy = IpConfiguration.ProxySettings.STATIC; 1904 // Construct a new HTTP Proxy 1905 httpProxyCopy = new ProxyInfo(httpProxy.getHost(), httpProxy.getPort(), 1906 httpProxy.getExclusionListAsString()); 1907 } 1908 if (!httpProxyCopy.isValid()) { 1909 throw new IllegalArgumentException("Invalid ProxyInfo: " + httpProxyCopy.toString()); 1910 } 1911 mIpConfiguration.setProxySettings(proxySettingCopy); 1912 mIpConfiguration.setHttpProxy(httpProxyCopy); 1913 } 1914 1915 /** @hide */ setProxy(ProxySettings settings, ProxyInfo proxy)1916 public void setProxy(ProxySettings settings, ProxyInfo proxy) { 1917 mIpConfiguration.proxySettings = settings; 1918 mIpConfiguration.httpProxy = proxy; 1919 } 1920 1921 /** Implement the Parcelable interface {@hide} */ describeContents()1922 public int describeContents() { 1923 return 0; 1924 } 1925 1926 /** @hide */ setPasspointManagementObjectTree(String passpointManagementObjectTree)1927 public void setPasspointManagementObjectTree(String passpointManagementObjectTree) { 1928 mPasspointManagementObjectTree = passpointManagementObjectTree; 1929 } 1930 1931 /** @hide */ getMoTree()1932 public String getMoTree() { 1933 return mPasspointManagementObjectTree; 1934 } 1935 1936 /** copy constructor {@hide} */ WifiConfiguration(WifiConfiguration source)1937 public WifiConfiguration(WifiConfiguration source) { 1938 if (source != null) { 1939 networkId = source.networkId; 1940 status = source.status; 1941 SSID = source.SSID; 1942 BSSID = source.BSSID; 1943 FQDN = source.FQDN; 1944 roamingConsortiumIds = source.roamingConsortiumIds.clone(); 1945 providerFriendlyName = source.providerFriendlyName; 1946 isHomeProviderNetwork = source.isHomeProviderNetwork; 1947 preSharedKey = source.preSharedKey; 1948 1949 mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus()); 1950 apBand = source.apBand; 1951 apChannel = source.apChannel; 1952 1953 wepKeys = new String[4]; 1954 for (int i = 0; i < wepKeys.length; i++) { 1955 wepKeys[i] = source.wepKeys[i]; 1956 } 1957 1958 wepTxKeyIndex = source.wepTxKeyIndex; 1959 priority = source.priority; 1960 hiddenSSID = source.hiddenSSID; 1961 allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); 1962 allowedProtocols = (BitSet) source.allowedProtocols.clone(); 1963 allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); 1964 allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); 1965 allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); 1966 enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); 1967 1968 defaultGwMacAddress = source.defaultGwMacAddress; 1969 1970 mIpConfiguration = new IpConfiguration(source.mIpConfiguration); 1971 1972 if ((source.linkedConfigurations != null) 1973 && (source.linkedConfigurations.size() > 0)) { 1974 linkedConfigurations = new HashMap<String, Integer>(); 1975 linkedConfigurations.putAll(source.linkedConfigurations); 1976 } 1977 mCachedConfigKey = null; //force null configKey 1978 selfAdded = source.selfAdded; 1979 validatedInternetAccess = source.validatedInternetAccess; 1980 isLegacyPasspointConfig = source.isLegacyPasspointConfig; 1981 ephemeral = source.ephemeral; 1982 meteredHint = source.meteredHint; 1983 meteredOverride = source.meteredOverride; 1984 useExternalScores = source.useExternalScores; 1985 if (source.visibility != null) { 1986 visibility = new Visibility(source.visibility); 1987 } 1988 1989 lastFailure = source.lastFailure; 1990 didSelfAdd = source.didSelfAdd; 1991 lastConnectUid = source.lastConnectUid; 1992 lastUpdateUid = source.lastUpdateUid; 1993 creatorUid = source.creatorUid; 1994 creatorName = source.creatorName; 1995 lastUpdateName = source.lastUpdateName; 1996 peerWifiConfiguration = source.peerWifiConfiguration; 1997 1998 lastConnected = source.lastConnected; 1999 lastDisconnected = source.lastDisconnected; 2000 lastConnectionFailure = source.lastConnectionFailure; 2001 lastRoamingFailure = source.lastRoamingFailure; 2002 lastRoamingFailureReason = source.lastRoamingFailureReason; 2003 roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli; 2004 numScorerOverride = source.numScorerOverride; 2005 numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; 2006 numAssociation = source.numAssociation; 2007 userApproved = source.userApproved; 2008 numNoInternetAccessReports = source.numNoInternetAccessReports; 2009 noInternetAccessExpected = source.noInternetAccessExpected; 2010 creationTime = source.creationTime; 2011 updateTime = source.updateTime; 2012 shared = source.shared; 2013 } 2014 } 2015 2016 /** Implement the Parcelable interface {@hide} */ 2017 @Override writeToParcel(Parcel dest, int flags)2018 public void writeToParcel(Parcel dest, int flags) { 2019 dest.writeInt(networkId); 2020 dest.writeInt(status); 2021 mNetworkSelectionStatus.writeToParcel(dest); 2022 dest.writeString(SSID); 2023 dest.writeString(BSSID); 2024 dest.writeInt(apBand); 2025 dest.writeInt(apChannel); 2026 dest.writeString(FQDN); 2027 dest.writeString(providerFriendlyName); 2028 dest.writeInt(isHomeProviderNetwork ? 1 : 0); 2029 dest.writeInt(roamingConsortiumIds.length); 2030 for (long roamingConsortiumId : roamingConsortiumIds) { 2031 dest.writeLong(roamingConsortiumId); 2032 } 2033 dest.writeString(preSharedKey); 2034 for (String wepKey : wepKeys) { 2035 dest.writeString(wepKey); 2036 } 2037 dest.writeInt(wepTxKeyIndex); 2038 dest.writeInt(priority); 2039 dest.writeInt(hiddenSSID ? 1 : 0); 2040 dest.writeInt(requirePMF ? 1 : 0); 2041 dest.writeString(updateIdentifier); 2042 2043 writeBitSet(dest, allowedKeyManagement); 2044 writeBitSet(dest, allowedProtocols); 2045 writeBitSet(dest, allowedAuthAlgorithms); 2046 writeBitSet(dest, allowedPairwiseCiphers); 2047 writeBitSet(dest, allowedGroupCiphers); 2048 2049 dest.writeParcelable(enterpriseConfig, flags); 2050 2051 dest.writeParcelable(mIpConfiguration, flags); 2052 dest.writeString(dhcpServer); 2053 dest.writeString(defaultGwMacAddress); 2054 dest.writeInt(selfAdded ? 1 : 0); 2055 dest.writeInt(didSelfAdd ? 1 : 0); 2056 dest.writeInt(validatedInternetAccess ? 1 : 0); 2057 dest.writeInt(isLegacyPasspointConfig ? 1 : 0); 2058 dest.writeInt(ephemeral ? 1 : 0); 2059 dest.writeInt(meteredHint ? 1 : 0); 2060 dest.writeInt(meteredOverride ? 1 : 0); 2061 dest.writeInt(useExternalScores ? 1 : 0); 2062 dest.writeInt(creatorUid); 2063 dest.writeInt(lastConnectUid); 2064 dest.writeInt(lastUpdateUid); 2065 dest.writeString(creatorName); 2066 dest.writeString(lastUpdateName); 2067 dest.writeLong(lastConnectionFailure); 2068 dest.writeLong(lastRoamingFailure); 2069 dest.writeInt(lastRoamingFailureReason); 2070 dest.writeLong(roamingFailureBlackListTimeMilli); 2071 dest.writeInt(numScorerOverride); 2072 dest.writeInt(numScorerOverrideAndSwitchedNetwork); 2073 dest.writeInt(numAssociation); 2074 dest.writeInt(userApproved); 2075 dest.writeInt(numNoInternetAccessReports); 2076 dest.writeInt(noInternetAccessExpected ? 1 : 0); 2077 dest.writeInt(shared ? 1 : 0); 2078 dest.writeString(mPasspointManagementObjectTree); 2079 } 2080 2081 /** Implement the Parcelable interface {@hide} */ 2082 public static final Creator<WifiConfiguration> CREATOR = 2083 new Creator<WifiConfiguration>() { 2084 public WifiConfiguration createFromParcel(Parcel in) { 2085 WifiConfiguration config = new WifiConfiguration(); 2086 config.networkId = in.readInt(); 2087 config.status = in.readInt(); 2088 config.mNetworkSelectionStatus.readFromParcel(in); 2089 config.SSID = in.readString(); 2090 config.BSSID = in.readString(); 2091 config.apBand = in.readInt(); 2092 config.apChannel = in.readInt(); 2093 config.FQDN = in.readString(); 2094 config.providerFriendlyName = in.readString(); 2095 config.isHomeProviderNetwork = in.readInt() != 0; 2096 int numRoamingConsortiumIds = in.readInt(); 2097 config.roamingConsortiumIds = new long[numRoamingConsortiumIds]; 2098 for (int i = 0; i < numRoamingConsortiumIds; i++) { 2099 config.roamingConsortiumIds[i] = in.readLong(); 2100 } 2101 config.preSharedKey = in.readString(); 2102 for (int i = 0; i < config.wepKeys.length; i++) { 2103 config.wepKeys[i] = in.readString(); 2104 } 2105 config.wepTxKeyIndex = in.readInt(); 2106 config.priority = in.readInt(); 2107 config.hiddenSSID = in.readInt() != 0; 2108 config.requirePMF = in.readInt() != 0; 2109 config.updateIdentifier = in.readString(); 2110 2111 config.allowedKeyManagement = readBitSet(in); 2112 config.allowedProtocols = readBitSet(in); 2113 config.allowedAuthAlgorithms = readBitSet(in); 2114 config.allowedPairwiseCiphers = readBitSet(in); 2115 config.allowedGroupCiphers = readBitSet(in); 2116 2117 config.enterpriseConfig = in.readParcelable(null); 2118 config.mIpConfiguration = in.readParcelable(null); 2119 config.dhcpServer = in.readString(); 2120 config.defaultGwMacAddress = in.readString(); 2121 config.selfAdded = in.readInt() != 0; 2122 config.didSelfAdd = in.readInt() != 0; 2123 config.validatedInternetAccess = in.readInt() != 0; 2124 config.isLegacyPasspointConfig = in.readInt() != 0; 2125 config.ephemeral = in.readInt() != 0; 2126 config.meteredHint = in.readInt() != 0; 2127 config.meteredOverride = in.readInt() != 0; 2128 config.useExternalScores = in.readInt() != 0; 2129 config.creatorUid = in.readInt(); 2130 config.lastConnectUid = in.readInt(); 2131 config.lastUpdateUid = in.readInt(); 2132 config.creatorName = in.readString(); 2133 config.lastUpdateName = in.readString(); 2134 config.lastConnectionFailure = in.readLong(); 2135 config.lastRoamingFailure = in.readLong(); 2136 config.lastRoamingFailureReason = in.readInt(); 2137 config.roamingFailureBlackListTimeMilli = in.readLong(); 2138 config.numScorerOverride = in.readInt(); 2139 config.numScorerOverrideAndSwitchedNetwork = in.readInt(); 2140 config.numAssociation = in.readInt(); 2141 config.userApproved = in.readInt(); 2142 config.numNoInternetAccessReports = in.readInt(); 2143 config.noInternetAccessExpected = in.readInt() != 0; 2144 config.shared = in.readInt() != 0; 2145 config.mPasspointManagementObjectTree = in.readString(); 2146 return config; 2147 } 2148 2149 public WifiConfiguration[] newArray(int size) { 2150 return new WifiConfiguration[size]; 2151 } 2152 }; 2153 2154 /** 2155 * Serializes the object for backup 2156 * @hide 2157 */ getBytesForBackup()2158 public byte[] getBytesForBackup() throws IOException { 2159 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 2160 DataOutputStream out = new DataOutputStream(baos); 2161 2162 out.writeInt(BACKUP_VERSION); 2163 BackupUtils.writeString(out, SSID); 2164 out.writeInt(apBand); 2165 out.writeInt(apChannel); 2166 BackupUtils.writeString(out, preSharedKey); 2167 out.writeInt(getAuthType()); 2168 return baos.toByteArray(); 2169 } 2170 2171 /** 2172 * Deserializes a byte array into the WiFiConfiguration Object 2173 * @hide 2174 */ getWifiConfigFromBackup(DataInputStream in)2175 public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException, 2176 BackupUtils.BadVersionException { 2177 WifiConfiguration config = new WifiConfiguration(); 2178 int version = in.readInt(); 2179 if (version < 1 || version > BACKUP_VERSION) { 2180 throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); 2181 } 2182 2183 if (version == 1) return null; // Version 1 is a bad dataset. 2184 2185 config.SSID = BackupUtils.readString(in); 2186 config.apBand = in.readInt(); 2187 config.apChannel = in.readInt(); 2188 config.preSharedKey = BackupUtils.readString(in); 2189 config.allowedKeyManagement.set(in.readInt()); 2190 return config; 2191 } 2192 } 2193