/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.wifi; import android.annotation.SystemApi; import android.content.pm.PackageManager; import android.net.IpConfiguration; import android.net.IpConfiguration.ProxySettings; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Log; import java.util.HashMap; import java.util.BitSet; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; /** * A class representing a configured Wi-Fi network, including the * security configuration. */ public class WifiConfiguration implements Parcelable { private static final String TAG = "WifiConfiguration"; /** {@hide} */ public static final String ssidVarName = "ssid"; /** {@hide} */ public static final String bssidVarName = "bssid"; /** {@hide} */ public static final String pskVarName = "psk"; /** {@hide} */ public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; /** {@hide} */ public static final String wepTxKeyIdxVarName = "wep_tx_keyidx"; /** {@hide} */ public static final String priorityVarName = "priority"; /** {@hide} */ public static final String hiddenSSIDVarName = "scan_ssid"; /** {@hide} */ public static final String pmfVarName = "ieee80211w"; /** {@hide} */ public static final String updateIdentiferVarName = "update_identifier"; /** {@hide} */ public static final int INVALID_NETWORK_ID = -1; /** * Recognized key management schemes. */ public static class KeyMgmt { private KeyMgmt() { } /** WPA is not used; plaintext or static WEP could be used. */ public static final int NONE = 0; /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */ public static final int WPA_PSK = 1; /** WPA using EAP authentication. Generally used with an external authentication server. */ public static final int WPA_EAP = 2; /** IEEE 802.1X using EAP authentication and (optionally) dynamically * generated WEP keys. */ public static final int IEEE8021X = 3; /** WPA2 pre-shared key for use with soft access point * (requires {@code preSharedKey} to be specified). * @hide */ public static final int WPA2_PSK = 4; public static final String varName = "key_mgmt"; public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X", "WPA2_PSK" }; } /** * Recognized security protocols. */ public static class Protocol { private Protocol() { } /** WPA/IEEE 802.11i/D3.0 */ public static final int WPA = 0; /** WPA2/IEEE 802.11i */ public static final int RSN = 1; public static final String varName = "proto"; public static final String[] strings = { "WPA", "RSN" }; } /** * Recognized IEEE 802.11 authentication algorithms. */ public static class AuthAlgorithm { private AuthAlgorithm() { } /** Open System authentication (required for WPA/WPA2) */ public static final int OPEN = 0; /** Shared Key authentication (requires static WEP keys) */ public static final int SHARED = 1; /** LEAP/Network EAP (only used with LEAP) */ public static final int LEAP = 2; public static final String varName = "auth_alg"; public static final String[] strings = { "OPEN", "SHARED", "LEAP" }; } /** * Recognized pairwise ciphers for WPA. */ public static class PairwiseCipher { private PairwiseCipher() { } /** Use only Group keys (deprecated) */ public static final int NONE = 0; /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ public static final int TKIP = 1; /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ public static final int CCMP = 2; public static final String varName = "pairwise"; public static final String[] strings = { "NONE", "TKIP", "CCMP" }; } /** * Recognized group ciphers. *
* CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) **/ public static class GroupCipher { private GroupCipher() { } /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */ public static final int WEP40 = 0; /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */ public static final int WEP104 = 1; /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */ public static final int TKIP = 2; /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ public static final int CCMP = 3; public static final String varName = "group"; public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" }; } /** Possible status of a network configuration. */ public static class Status { private Status() { } /** this is the network we are currently connected to */ public static final int CURRENT = 0; /** supplicant will not attempt to use this network */ public static final int DISABLED = 1; /** supplicant will consider this network available for association */ public static final int ENABLED = 2; public static final String[] strings = { "current", "disabled", "enabled" }; } /** @hide */ public static final int DISABLED_UNKNOWN_REASON = 0; /** @hide */ public static final int DISABLED_DNS_FAILURE = 1; /** @hide */ public static final int DISABLED_DHCP_FAILURE = 2; /** @hide */ public static final int DISABLED_AUTH_FAILURE = 3; /** @hide */ public static final int DISABLED_ASSOCIATION_REJECT = 4; /** @hide */ public static final int DISABLED_BY_WIFI_MANAGER = 5; /** @hide */ public static final int UNKNOWN_UID = -1; /** * The ID number that the supplicant uses to identify this * network configuration entry. This must be passed as an argument * to most calls into the supplicant. */ public int networkId; /** * The current status of this network configuration entry. * @see Status */ public int status; /** * The configuration needs to be written to networkHistory.txt * @hide */ public boolean dirty; /** * The code referring to a reason for disabling the network * Valid when {@link #status} == Status.DISABLED * @hide */ public int disableReason; /** * The network's SSID. Can either be an ASCII string, * which must be enclosed in double quotation marks * (e.g., {@code "MyNetwork"}, or a string of * hex digits,which are not enclosed in quotes * (e.g., {@code 01a243f405}). */ public String SSID; /** * When set, this network configuration entry should only be used when * associating with the AP having the specified BSSID. The value is * a string in the format of an Ethernet MAC address, e.g., *
XX:XX:XX:XX:XX:XX
where each X
is a hex digit.
*/
public String BSSID;
/**
* The band which AP resides on
* 0-2G 1-5G
* By default, 2G is chosen
* @hide
*/
public int apBand = 0;
/**
* The channel which AP resides on,currently, US only
* 2G 1-11
* 5G 36,40,44,48,149,153,157,161,165
* 0 - find a random available channel according to the apBand
* @hide
*/
public int apChannel = 0;
/**
* Pre-shared key for use with WPA-PSK.
*
* When the value of this key is read, the actual key is
* not returned, just a "*" if the key has a value, or the null
* string otherwise.
*/
public String preSharedKey;
/**
* Up to four WEP keys. Either an ASCII string enclosed in double
* quotation marks (e.g., {@code "abcdef"} or a string
* of hex digits (e.g., {@code 0102030405}).
*
* When the value of one of these keys is read, the actual key is
* not returned, just a "*" if the key has a value, or the null
* string otherwise.
*/
public String[] wepKeys;
/** Default WEP key index, ranging from 0 to 3. */
public int wepTxKeyIndex;
/**
* Priority determines the preference given to a network by {@code wpa_supplicant}
* when choosing an access point with which to associate.
*/
public int priority;
/**
* This is a network that does not broadcast its SSID, so an
* SSID-specific probe request must be used for scans.
*/
public boolean hiddenSSID;
/**
* This is a network that requries Protected Management Frames (PMF).
* @hide
*/
public boolean requirePMF;
/**
* Update identifier, for Passpoint network.
* @hide
*/
public String updateIdentifier;
/**
* The set of key management protocols supported by this configuration.
* See {@link KeyMgmt} for descriptions of the values.
* Defaults to WPA-PSK WPA-EAP.
*/
public BitSet allowedKeyManagement;
/**
* The set of security protocols supported by this configuration.
* See {@link Protocol} for descriptions of the values.
* Defaults to WPA RSN.
*/
public BitSet allowedProtocols;
/**
* The set of authentication protocols supported by this configuration.
* See {@link AuthAlgorithm} for descriptions of the values.
* Defaults to automatic selection.
*/
public BitSet allowedAuthAlgorithms;
/**
* The set of pairwise ciphers for WPA supported by this configuration.
* See {@link PairwiseCipher} for descriptions of the values.
* Defaults to CCMP TKIP.
*/
public BitSet allowedPairwiseCiphers;
/**
* The set of group ciphers supported by this configuration.
* See {@link GroupCipher} for descriptions of the values.
* Defaults to CCMP TKIP WEP104 WEP40.
*/
public BitSet allowedGroupCiphers;
/**
* The enterprise configuration details specifying the EAP method,
* certificates and other settings associated with the EAP.
*/
public WifiEnterpriseConfig enterpriseConfig;
/**
* Fully qualified domain name of a passpoint configuration
*/
public String FQDN;
/**
* Name of passpoint credential provider
*/
public String providerFriendlyName;
/**
* Roaming Consortium Id list for passpoint credential; identifies a set of networks where
* passpoint credential will be considered valid
*/
public long[] roamingConsortiumIds;
/**
* @hide
*/
private IpConfiguration mIpConfiguration;
/**
* @hide
* dhcp server MAC address if known
*/
public String dhcpServer;
/**
* @hide
* default Gateway MAC address if known
*/
public String defaultGwMacAddress;
/**
* @hide
* last failure
*/
public String lastFailure;
/**
* @hide
* last time we connected, this configuration had validated internet access
*/
public boolean validatedInternetAccess;
/**
* @hide
* Uid of app creating the configuration
*/
@SystemApi
public int creatorUid;
/**
* @hide
* Uid of last app issuing a connection related command
*/
public int lastConnectUid;
/**
* @hide
* Uid of last app modifying the configuration
*/
@SystemApi
public int lastUpdateUid;
/**
* @hide
* Universal name for app creating the configuration
* see {#link {@link PackageManager#getNameForUid(int)}
*/
@SystemApi
public String creatorName;
/**
* @hide
* Universal name for app updating the configuration
* see {#link {@link PackageManager#getNameForUid(int)}
*/
@SystemApi
public String lastUpdateName;
/**
* @hide
* Uid used by autoJoin
*/
public String autoJoinBSSID;
/**
* @hide
* Status of user approval for connection
*/
public int userApproved = USER_UNSPECIFIED;
/** The Below RSSI thresholds are used to configure AutoJoin
* - GOOD/LOW/BAD thresholds are used so as to calculate link score
* - UNWANTED_SOFT are used by the blacklisting logic so as to handle
* the unwanted network message coming from CS
* - UNBLACKLIST thresholds are used so as to tweak the speed at which
* the network is unblacklisted (i.e. if
* it is seen with good RSSI, it is blacklisted faster)
* - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from
* the network we need to be before autojoin kicks in
*/
/** @hide **/
public static int INVALID_RSSI = -127;
/** @hide **/
public static int UNWANTED_BLACKLIST_SOFT_RSSI_24 = -80;
/** @hide **/
public static int UNWANTED_BLACKLIST_SOFT_RSSI_5 = -70;
/** @hide **/
public static int GOOD_RSSI_24 = -65;
/** @hide **/
public static int LOW_RSSI_24 = -77;
/** @hide **/
public static int BAD_RSSI_24 = -87;
/** @hide **/
public static int GOOD_RSSI_5 = -60;
/** @hide **/
public static int LOW_RSSI_5 = -72;
/** @hide **/
public static int BAD_RSSI_5 = -82;
/** @hide **/
public static int UNWANTED_BLACKLIST_SOFT_BUMP = 4;
/** @hide **/
public static int UNWANTED_BLACKLIST_HARD_BUMP = 8;
/** @hide **/
public static int UNBLACKLIST_THRESHOLD_24_SOFT = -77;
/** @hide **/
public static int UNBLACKLIST_THRESHOLD_24_HARD = -68;
/** @hide **/
public static int UNBLACKLIST_THRESHOLD_5_SOFT = -63;
/** @hide **/
public static int UNBLACKLIST_THRESHOLD_5_HARD = -56;
/** @hide **/
public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_24 = -80;
/** @hide **/
public static int INITIAL_AUTO_JOIN_ATTEMPT_MIN_5 = -70;
/** @hide
* 5GHz band is prefered low over 2.4 if the 5GHz RSSI is higher than this threshold */
public static int A_BAND_PREFERENCE_RSSI_THRESHOLD = -65;
/** @hide
* 5GHz band is penalized if the 5GHz RSSI is lower than this threshold **/
public static int G_BAND_PREFERENCE_RSSI_THRESHOLD = -75;
/** @hide
* Boost given to RSSI on a home network for the purpose of calculating the score
* This adds stickiness to home networks, as defined by:
* - less than 4 known BSSIDs
* - PSK only
* - TODO: add a test to verify that all BSSIDs are behind same gateway
***/
public static int HOME_NETWORK_RSSI_BOOST = 5;
/** @hide
* RSSI boost for configuration which use autoJoinUseAggressiveJoinAttemptThreshold
* To be more aggressive when initially attempting to auto join
*/
public static int MAX_INITIAL_AUTO_JOIN_RSSI_BOOST = 8;
/**
* @hide
* A summary of the RSSI and Band status for that configuration
* This is used as a temporary value by the auto-join controller
*/
public static final class Visibility {
public int rssi5; // strongest 5GHz RSSI
public int rssi24; // strongest 2.4GHz RSSI
public int num5; // number of BSSIDs on 5GHz
public int num24; // number of BSSIDs on 2.4GHz
public long age5; // timestamp of the strongest 5GHz BSSID (last time it was seen)
public long age24; // timestamp of the strongest 2.4GHz BSSID (last time it was seen)
public String BSSID24;
public String BSSID5;
public int score; // Debug only, indicate last score used for autojoin/cell-handover
public int currentNetworkBoost; // Debug only, indicate boost applied to RSSI if current
public int bandPreferenceBoost; // Debug only, indicate boost applied to RSSI if current
public int lastChoiceBoost; // Debug only, indicate last choice applied to this configuration
public String lastChoiceConfig; // Debug only, indicate last choice applied to this configuration
public Visibility() {
rssi5 = INVALID_RSSI;
rssi24 = INVALID_RSSI;
}
public Visibility(Visibility source) {
rssi5 = source.rssi5;
rssi24 = source.rssi24;
age24 = source.age24;
age5 = source.age5;
num24 = source.num24;
num5 = source.num5;
BSSID5 = source.BSSID5;
BSSID24 = source.BSSID24;
}
@Override
public String toString() {
StringBuilder sbuf = new StringBuilder();
sbuf.append("[");
if (rssi24 > INVALID_RSSI) {
sbuf.append(Integer.toString(rssi24));
sbuf.append(",");
sbuf.append(Integer.toString(num24));
if (BSSID24 != null) sbuf.append(",").append(BSSID24);
}
sbuf.append("; ");
if (rssi5 > INVALID_RSSI) {
sbuf.append(Integer.toString(rssi5));
sbuf.append(",");
sbuf.append(Integer.toString(num5));
if (BSSID5 != null) sbuf.append(",").append(BSSID5);
}
if (score != 0) {
sbuf.append("; ").append(score);
sbuf.append(", ").append(currentNetworkBoost);
sbuf.append(", ").append(bandPreferenceBoost);
if (lastChoiceConfig != null) {
sbuf.append(", ").append(lastChoiceBoost);
sbuf.append(", ").append(lastChoiceConfig);
}
}
sbuf.append("]");
return sbuf.toString();
}
}
/** @hide
* Cache the visibility status of this configuration.
* Visibility can change at any time depending on scan results availability.
* Owner of the WifiConfiguration is responsible to set this field based on
* recent scan results.
***/
public Visibility visibility;
/** @hide
* calculate and set Visibility for that configuration.
*
* age in milliseconds: we will consider only ScanResults that are more recent,
* i.e. younger.
***/
public void setVisibility(Visibility status) {
visibility = status;
}
/** @hide */
public static final int AUTO_JOIN_ENABLED = 0;
/**
* if this is set, the WifiConfiguration cannot use linkages so as to bump
* it's relative priority.
* - status between and 128 indicate various level of blacklisting depending
* on the severity or frequency of the connection error
* - deleted status indicates that the user is deleting the configuration, and so
* although it may have been self added we will not re-self-add it, ignore it,
* not return it to applications, and not connect to it
* */
/** @hide
* network was temporary disabled due to bad connection, most likely due
* to weak RSSI */
public static final int AUTO_JOIN_TEMPORARY_DISABLED = 1;
/** @hide
* network was temporary disabled due to bad connection, which cant be attributed
* to weak RSSI */
public static final int AUTO_JOIN_TEMPORARY_DISABLED_LINK_ERRORS = 32;
/** @hide */
public static final int AUTO_JOIN_TEMPORARY_DISABLED_AT_SUPPLICANT = 64;
/** @hide */
public static final int AUTO_JOIN_DISABLED_ON_AUTH_FAILURE = 128;
/** @hide */
public static final int AUTO_JOIN_DISABLED_NO_CREDENTIALS = 160;
/** @hide */
public static final int AUTO_JOIN_DISABLED_USER_ACTION = 161;
/** @hide */
public static final int AUTO_JOIN_DELETED = 200;
// States for the userApproved field
/**
* @hide
* User hasn't specified if connection is okay
*/
public static final int USER_UNSPECIFIED = 0;
/**
* @hide
* User has approved this for connection
*/
public static final int USER_APPROVED = 1;
/**
* @hide
* User has banned this from connection
*/
public static final int USER_BANNED = 2;
/**
* @hide
* Waiting for user input
*/
public static final int USER_PENDING = 3;
/**
* @hide
*/
public int autoJoinStatus;
/**
* @hide
* Number of connection failures
*/
public int numConnectionFailures;
/**
* @hide
* Number of IP config failures
*/
public int numIpConfigFailures;
/**
* @hide
* Number of Auth failures
*/
public int numAuthFailures;
/**
* @hide
* Number of reports indicating no Internet Access
*/
public int numNoInternetAccessReports;
/**
* @hide
* For debug: date at which the config was last updated
*/
public String updateTime;
/**
* @hide
* For debug: date at which the config was last updated
*/
public String creationTime;
/**
* @hide
* The WiFi configuration is considered to have no internet access for purpose of autojoining
* if there has been a report of it having no internet access, and, it never have had
* internet access in the past.
*/
public boolean hasNoInternetAccess() {
return numNoInternetAccessReports > 0 && !validatedInternetAccess;
}
/**
* The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
* Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
* this configuration and selects "don't ask again".
* @hide
*/
public boolean noInternetAccessExpected;
/**
* @hide
* Last time we blacklisted the configuration
*/
public long blackListTimestamp;
/**
* @hide
* Last time the system was connected to this configuration.
*/
public long lastConnected;
/**
* @hide
* Last time the system tried to connect and failed.
*/
public long lastConnectionFailure;
/**
* @hide
* Last time the system tried to roam and failed because of authentication failure or DHCP
* RENEW failure.
*/
public long lastRoamingFailure;
/** @hide */
public static int ROAMING_FAILURE_IP_CONFIG = 1;
/** @hide */
public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
/**
* @hide
* Initial amount of time this Wifi configuration gets blacklisted for network switching
* because of roaming failure
*/
public long roamingFailureBlackListTimeMilli = 1000;
/**
* @hide
* Last roaming failure reason code
*/
public int lastRoamingFailureReason;
/**
* @hide
* Last time the system was disconnected to this configuration.
*/
public long lastDisconnected;
/**
* Set if the configuration was self added by the framework
* This boolean is cleared if we get a connect/save/ update or
* any wifiManager command that indicate the user interacted with the configuration
* since we will now consider that the configuration belong to him.
* @hide
*/
public boolean selfAdded;
/**
* Set if the configuration was self added by the framework
* This boolean is set once and never cleared. It is used
* so as we never loose track of who created the
* configuration in the first place.
* @hide
*/
public boolean didSelfAdd;
/**
* Peer WifiConfiguration this WifiConfiguration was added for
* @hide
*/
public String peerWifiConfiguration;
/**
* @hide
* Indicate that a WifiConfiguration is temporary and should not be saved
* nor considered by AutoJoin.
*/
public boolean ephemeral;
/**
* @hide
* Indicate that we didn't auto-join because rssi was too low
*/
public boolean autoJoinBailedDueToLowRssi;
/**
* @hide
* AutoJoin even though RSSI is 10dB below threshold
*/
public int autoJoinUseAggressiveJoinAttemptThreshold;
/**
* @hide
* Number of time the scorer overrode a the priority based choice, when comparing two
* WifiConfigurations, note that since comparing WifiConfiguration happens very often
* potentially at every scan, this number might become very large, even on an idle
* system.
*/
@SystemApi
public int numScorerOverride;
/**
* @hide
* Number of time the scorer overrode a the priority based choice, and the comparison
* triggered a network switch
*/
@SystemApi
public int numScorerOverrideAndSwitchedNetwork;
/**
* @hide
* Number of time we associated to this configuration.
*/
@SystemApi
public int numAssociation;
/**
* @hide
* Number of time user disabled WiFi while associated to this configuration with Low RSSI.
*/
public int numUserTriggeredWifiDisableLowRSSI;
/**
* @hide
* Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
*/
public int numUserTriggeredWifiDisableBadRSSI;
/**
* @hide
* Number of time user disabled WiFi while associated to this configuration
* and RSSI was not HIGH.
*/
public int numUserTriggeredWifiDisableNotHighRSSI;
/**
* @hide
* Number of ticks associated to this configuration with Low RSSI.
*/
public int numTicksAtLowRSSI;
/**
* @hide
* Number of ticks associated to this configuration with Bad RSSI.
*/
public int numTicksAtBadRSSI;
/**
* @hide
* Number of ticks associated to this configuration
* and RSSI was not HIGH.
*/
public int numTicksAtNotHighRSSI;
/**
* @hide
* Number of time user (WifiManager) triggered association to this configuration.
* TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
*/
public int numUserTriggeredJoinAttempts;
/**
* @hide
* Connect choices
*
* remember the keys identifying the known WifiConfiguration over which this configuration
* was preferred by user or a "WiFi Network Management app", that is,
* a WifiManager.CONNECT_NETWORK or SELECT_NETWORK was received while this configuration
* was visible to the user:
* configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
*
* The integer represents the configuration's RSSI at that time (useful?)
*
* The overall auto-join algorithm make use of past connect choice so as to sort configuration,
* the exact algorithm still fluctuating as of 5/7/2014
*
*/
public HashMap