| /* |
| * 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.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.SystemApi; |
| import android.annotation.UnsupportedAppUsage; |
| import android.content.pm.PackageManager; |
| import android.net.IpConfiguration; |
| import android.net.IpConfiguration.ProxySettings; |
| import android.net.MacAddress; |
| import android.net.NetworkSpecifier; |
| import android.net.ProxyInfo; |
| import android.net.StaticIpConfiguration; |
| import android.net.Uri; |
| import android.os.Build; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.os.SystemClock; |
| import android.os.UserHandle; |
| import android.text.TextUtils; |
| import android.util.BackupUtils; |
| import android.util.Log; |
| import android.util.TimeUtils; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.DataInputStream; |
| import java.io.DataOutputStream; |
| import java.io.IOException; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.Arrays; |
| import java.util.BitSet; |
| import java.util.HashMap; |
| |
| /** |
| * A class representing a configured Wi-Fi network, including the |
| * security configuration. |
| * |
| * @deprecated Use {@link WifiNetworkSpecifier.Builder} to create {@link NetworkSpecifier} and |
| * {@link WifiNetworkSuggestion.Builder} to create {@link WifiNetworkSuggestion}. This will become a |
| * system use only object in the future. |
| */ |
| @Deprecated |
| public class WifiConfiguration implements Parcelable { |
| private static final String TAG = "WifiConfiguration"; |
| /** |
| * Current Version of the Backup Serializer. |
| */ |
| private static final int BACKUP_VERSION = 3; |
| /** {@hide} */ |
| public static final String ssidVarName = "ssid"; |
| /** {@hide} */ |
| public static final String bssidVarName = "bssid"; |
| /** {@hide} */ |
| public static final String pskVarName = "psk"; |
| /** {@hide} */ |
| @Deprecated |
| @UnsupportedAppUsage |
| public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" }; |
| /** {@hide} */ |
| @Deprecated |
| 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; |
| /** {@hide} */ |
| public static final int LOCAL_ONLY_NETWORK_ID = -2; |
| |
| /** {@hide} */ |
| private String mPasspointManagementObjectTree; |
| /** {@hide} */ |
| private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3; |
| |
| /** |
| * 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 |
| */ |
| @SystemApi |
| public static final int WPA2_PSK = 4; |
| /** |
| * Hotspot 2.0 r2 OSEN: |
| * @hide |
| */ |
| public static final int OSEN = 5; |
| |
| /** |
| * IEEE 802.11r Fast BSS Transition with PSK authentication. |
| * @hide |
| */ |
| public static final int FT_PSK = 6; |
| |
| /** |
| * IEEE 802.11r Fast BSS Transition with EAP authentication. |
| * @hide |
| */ |
| public static final int FT_EAP = 7; |
| |
| /** |
| * Simultaneous Authentication of Equals |
| */ |
| public static final int SAE = 8; |
| |
| /** |
| * Opportunististic Wireless Encryption |
| */ |
| public static final int OWE = 9; |
| |
| /** |
| * SUITE_B_192 192 bit level |
| */ |
| public static final int SUITE_B_192 = 10; |
| |
| /** |
| * WPA pre-shared key with stronger SHA256-based algorithms. |
| * @hide |
| */ |
| public static final int WPA_PSK_SHA256 = 11; |
| |
| /** |
| * WPA using EAP authentication with stronger SHA256-based algorithms. |
| * @hide |
| */ |
| public static final int WPA_EAP_SHA256 = 12; |
| |
| public static final String varName = "key_mgmt"; |
| |
| public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", |
| "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP", |
| "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256" }; |
| } |
| |
| /** |
| * Recognized security protocols. |
| */ |
| public static class Protocol { |
| private Protocol() { } |
| |
| /** WPA/IEEE 802.11i/D3.0 |
| * @deprecated Due to security and performance limitations, use of WPA-1 networks |
| * is discouraged. WPA-2 (RSN) should be used instead. */ |
| @Deprecated |
| public static final int WPA = 0; |
| /** RSN WPA2/WPA3/IEEE 802.11i */ |
| public static final int RSN = 1; |
| /** HS2.0 r2 OSEN |
| * @hide |
| */ |
| public static final int OSEN = 2; |
| |
| public static final String varName = "proto"; |
| |
| public static final String[] strings = { "WPA", "RSN", "OSEN" }; |
| } |
| |
| /** |
| * 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) |
| * @deprecated Due to security and performance limitations, use of WEP networks |
| * is discouraged. */ |
| @Deprecated |
| 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] |
| * @deprecated Due to security and performance limitations, use of WPA-1 networks |
| * is discouraged. WPA-2 (RSN) should be used instead. */ |
| @Deprecated |
| 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; |
| /** |
| * AES in Galois/Counter Mode |
| */ |
| public static final int GCMP_256 = 3; |
| |
| public static final String varName = "pairwise"; |
| |
| public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" }; |
| } |
| |
| /** |
| * Recognized group ciphers. |
| * <pre> |
| * 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) |
| * GCMP_256 = AES in Galois/Counter Mode |
| * </pre> |
| */ |
| public static class GroupCipher { |
| private GroupCipher() { } |
| |
| /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) |
| * @deprecated Due to security and performance limitations, use of WEP networks |
| * is discouraged. */ |
| @Deprecated |
| public static final int WEP40 = 0; |
| /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key |
| * @deprecated Due to security and performance limitations, use of WEP networks |
| * is discouraged. */ |
| @Deprecated |
| 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; |
| /** Hotspot 2.0 r2 OSEN |
| * @hide |
| */ |
| public static final int GTK_NOT_USED = 4; |
| /** |
| * AES in Galois/Counter Mode |
| */ |
| public static final int GCMP_256 = 5; |
| |
| public static final String varName = "group"; |
| |
| public static final String[] strings = |
| { /* deprecated */ "WEP40", /* deprecated */ "WEP104", |
| "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" }; |
| } |
| |
| /** |
| * Recognized group management ciphers. |
| * <pre> |
| * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits |
| * BIP_GMAC_128 = Galois Message Authentication Code 128 bits |
| * BIP_GMAC_256 = Galois Message Authentication Code 256 bits |
| * </pre> |
| */ |
| public static class GroupMgmtCipher { |
| private GroupMgmtCipher() { } |
| |
| /** CMAC-256 = Cipher-based Message Authentication Code */ |
| public static final int BIP_CMAC_256 = 0; |
| |
| /** GMAC-128 = Galois Message Authentication Code */ |
| public static final int BIP_GMAC_128 = 1; |
| |
| /** GMAC-256 = Galois Message Authentication Code */ |
| public static final int BIP_GMAC_256 = 2; |
| |
| private static final String varName = "groupMgmt"; |
| |
| private static final String[] strings = { "BIP_CMAC_256", |
| "BIP_GMAC_128", "BIP_GMAC_256"}; |
| } |
| |
| /** |
| * Recognized suiteB ciphers. |
| * <pre> |
| * ECDHE_ECDSA |
| * ECDHE_RSA |
| * </pre> |
| * @hide |
| */ |
| public static class SuiteBCipher { |
| private SuiteBCipher() { } |
| |
| /** Diffie-Hellman with Elliptic Curve_ECDSA signature */ |
| public static final int ECDHE_ECDSA = 0; |
| |
| /** Diffie-Hellman with_RSA signature */ |
| public static final int ECDHE_RSA = 1; |
| |
| private static final String varName = "SuiteB"; |
| |
| private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; |
| } |
| |
| /** 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" }; |
| } |
| |
| /** |
| * Security types we support. |
| */ |
| /** @hide */ |
| public static final int SECURITY_TYPE_OPEN = 0; |
| /** @hide */ |
| public static final int SECURITY_TYPE_WEP = 1; |
| /** @hide */ |
| public static final int SECURITY_TYPE_PSK = 2; |
| /** @hide */ |
| public static final int SECURITY_TYPE_EAP = 3; |
| /** @hide */ |
| public static final int SECURITY_TYPE_SAE = 4; |
| /** @hide */ |
| public static final int SECURITY_TYPE_EAP_SUITE_B = 5; |
| /** @hide */ |
| public static final int SECURITY_TYPE_OWE = 6; |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef(prefix = { "SECURITY_TYPE_" }, value = { |
| SECURITY_TYPE_OPEN, |
| SECURITY_TYPE_WEP, |
| SECURITY_TYPE_PSK, |
| SECURITY_TYPE_EAP, |
| SECURITY_TYPE_SAE, |
| SECURITY_TYPE_EAP_SUITE_B, |
| SECURITY_TYPE_OWE |
| }) |
| public @interface SecurityType {} |
| |
| /** |
| * @hide |
| * Set security params (sets the various bitsets exposed in WifiConfiguration). |
| * |
| * @param securityType One of the security types from {@link SecurityType}. |
| */ |
| public void setSecurityParams(@SecurityType int securityType) { |
| // Clear all the bitsets. |
| allowedKeyManagement.clear(); |
| allowedProtocols.clear(); |
| allowedAuthAlgorithms.clear(); |
| allowedPairwiseCiphers.clear(); |
| allowedGroupCiphers.clear(); |
| allowedGroupManagementCiphers.clear(); |
| allowedSuiteBCiphers.clear(); |
| |
| switch (securityType) { |
| case SECURITY_TYPE_OPEN: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); |
| break; |
| case SECURITY_TYPE_WEP: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); |
| allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); |
| allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); |
| break; |
| case SECURITY_TYPE_PSK: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); |
| break; |
| case SECURITY_TYPE_EAP: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); |
| break; |
| case SECURITY_TYPE_SAE: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); |
| requirePMF = true; |
| break; |
| case SECURITY_TYPE_EAP_SUITE_B: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); |
| allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); |
| allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); |
| allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA); |
| allowedSuiteBCiphers.set(WifiConfiguration.SuiteBCipher.ECDHE_RSA); |
| requirePMF = true; |
| break; |
| case SECURITY_TYPE_OWE: |
| allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); |
| requirePMF = true; |
| break; |
| default: |
| throw new IllegalArgumentException("unknown security type " + securityType); |
| } |
| } |
| |
| /** @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; |
| |
| // Fixme We need remove this field to use only Quality network selection status only |
| /** |
| * The current status of this network configuration entry. |
| * @see Status |
| */ |
| public int status; |
| |
| /** |
| * The network's SSID. Can either be a UTF-8 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., |
| * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit. |
| */ |
| public String BSSID; |
| |
| /** |
| * 2GHz band. |
| * @hide |
| */ |
| public static final int AP_BAND_2GHZ = 0; |
| |
| /** |
| * 5GHz band. |
| * @hide |
| */ |
| public static final int AP_BAND_5GHZ = 1; |
| |
| /** |
| * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability, |
| * operating country code and current radio conditions. |
| * @hide |
| */ |
| public static final int AP_BAND_ANY = -1; |
| |
| /** |
| * The band which AP resides on |
| * -1:Any 0:2G 1:5G |
| * By default, 2G is chosen |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public int apBand = AP_BAND_2GHZ; |
| |
| /** |
| * 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 |
| */ |
| @UnsupportedAppUsage |
| public int apChannel = 0; |
| |
| /** |
| * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in |
| * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or |
| * a string of 64 hex digits for raw PSK. |
| * <p/> |
| * 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; |
| |
| /** |
| * Four WEP keys. For each of the four values, provide either an ASCII |
| * string enclosed in double quotation marks (e.g., {@code "abcdef"}), |
| * a string of hex digits (e.g., {@code 0102030405}), or an empty string |
| * (e.g., {@code ""}). |
| * <p/> |
| * 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. |
| * @deprecated Due to security and performance limitations, use of WEP networks |
| * is discouraged. |
| */ |
| @Deprecated |
| public String[] wepKeys; |
| |
| /** Default WEP key index, ranging from 0 to 3. |
| * @deprecated Due to security and performance limitations, use of WEP networks |
| * is discouraged. */ |
| @Deprecated |
| public int wepTxKeyIndex; |
| |
| /** |
| * Priority determines the preference given to a network by {@code wpa_supplicant} |
| * when choosing an access point with which to associate. |
| * @deprecated This field does not exist anymore. |
| */ |
| @Deprecated |
| 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 set of group management ciphers supported by this configuration. |
| * See {@link GroupMgmtCipher} for descriptions of the values. |
| */ |
| public BitSet allowedGroupManagementCiphers; |
| /** |
| * The set of SuiteB ciphers supported by this configuration. |
| * To be used for WPA3-Enterprise mode. |
| * See {@link SuiteBCipher} for descriptions of the values. |
| */ |
| public BitSet allowedSuiteBCiphers; |
| /** |
| * 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; |
| |
| /** |
| * Flag indicating if this network is provided by a home Passpoint provider or a roaming |
| * Passpoint provider. This flag will be {@code true} if this network is provided by |
| * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider |
| * or is a non-Passpoint network. |
| */ |
| public boolean isHomeProviderNetwork; |
| |
| /** |
| * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where |
| * Passpoint credential will be considered valid |
| */ |
| public long[] roamingConsortiumIds; |
| |
| /** |
| * @hide |
| * This network configuration is visible to and usable by other users on the |
| * same device. |
| */ |
| @UnsupportedAppUsage |
| public boolean shared; |
| |
| /** |
| * @hide |
| */ |
| @NonNull |
| @UnsupportedAppUsage |
| private IpConfiguration mIpConfiguration; |
| |
| /** |
| * @hide |
| * dhcp server MAC address if known |
| */ |
| public String dhcpServer; |
| |
| /** |
| * @hide |
| * default Gateway MAC address if known |
| */ |
| @UnsupportedAppUsage |
| public String defaultGwMacAddress; |
| |
| /** |
| * @hide |
| * last time we connected, this configuration had validated internet access |
| */ |
| @UnsupportedAppUsage |
| public boolean validatedInternetAccess; |
| |
| /** |
| * @hide |
| * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM) |
| * This value is populated from scan results that contain Beacon Frames, which are infrequent. |
| * The value is not guaranteed to be set or current (Although it SHOULDNT change once set) |
| * Valid values are from 1 - 255. Initialized here as 0, use this to check if set. |
| */ |
| public int dtimInterval = 0; |
| |
| /** |
| * Flag indicating if this configuration represents a legacy Passpoint configuration |
| * (Release N or older). This is used for migrating Passpoint configuration from N to O. |
| * This will no longer be needed after O. |
| * @hide |
| */ |
| public boolean isLegacyPasspointConfig = false; |
| /** |
| * @hide |
| * Uid of app creating the configuration |
| */ |
| @SystemApi |
| public int creatorUid; |
| |
| /** |
| * @hide |
| * Uid of last app issuing a connection related command |
| */ |
| @UnsupportedAppUsage |
| 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 PackageManager#getNameForUid(int)} |
| */ |
| @SystemApi |
| public String creatorName; |
| |
| /** |
| * @hide |
| * Universal name for app updating the configuration |
| * see {@link PackageManager#getNameForUid(int)} |
| */ |
| @SystemApi |
| public String lastUpdateName; |
| |
| /** |
| * @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 **/ |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) |
| public static int INVALID_RSSI = -127; |
| |
| // 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 |
| * Number of reports indicating no Internet Access |
| */ |
| @UnsupportedAppUsage |
| 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. |
| */ |
| @SystemApi |
| 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 |
| */ |
| @UnsupportedAppUsage |
| public boolean noInternetAccessExpected; |
| |
| /** |
| * 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 |
| */ |
| @SystemApi |
| public boolean isNoInternetAccessExpected() { |
| return noInternetAccessExpected; |
| } |
| |
| /** |
| * This Wifi configuration is expected for OSU(Online Sign Up) of Passpoint Release 2. |
| * @hide |
| */ |
| public boolean osu; |
| |
| /** |
| * @hide |
| * Last time the system was connected to this configuration. |
| */ |
| public long lastConnected; |
| |
| /** |
| * @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 |
| */ |
| @UnsupportedAppUsage |
| 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 a WifiConfiguration is temporary and should not be saved |
| * nor considered by AutoJoin. |
| */ |
| @SystemApi |
| public boolean isEphemeral() { |
| return ephemeral; |
| } |
| |
| /** |
| * Indicate whther the network is trusted or not. Networks are considered trusted |
| * if the user explicitly allowed this network connection. |
| * @hide |
| */ |
| public boolean trusted; |
| |
| /** |
| * This Wifi configuration is created from a {@link WifiNetworkSuggestion} |
| * @hide |
| */ |
| public boolean fromWifiNetworkSuggestion; |
| |
| /** |
| * This Wifi configuration is created from a {@link WifiNetworkSpecifier} |
| * @hide |
| */ |
| public boolean fromWifiNetworkSpecifier; |
| |
| /** |
| * Indicates if the creator of this configuration has expressed that it |
| * should be considered metered. |
| * |
| * @see #isMetered(WifiConfiguration, WifiInfo) |
| * @hide |
| */ |
| @SystemApi |
| public boolean meteredHint; |
| |
| /** {@hide} */ |
| public static final int METERED_OVERRIDE_NONE = 0; |
| /** {@hide} */ |
| public static final int METERED_OVERRIDE_METERED = 1; |
| /** {@hide} */ |
| public static final int METERED_OVERRIDE_NOT_METERED = 2; |
| |
| /** |
| * Indicates if the end user has expressed an explicit opinion about the |
| * meteredness of this network, such as through the Settings app. |
| * <p> |
| * This should always override any values from {@link #meteredHint} or |
| * {@link WifiInfo#getMeteredHint()}. |
| * |
| * @see #isMetered(WifiConfiguration, WifiInfo) |
| * @hide |
| */ |
| public int meteredOverride = METERED_OVERRIDE_NONE; |
| |
| /** |
| * Blend together all the various opinions to decide if the given network |
| * should be considered metered or not. |
| * |
| * @hide |
| */ |
| public static boolean isMetered(WifiConfiguration config, WifiInfo info) { |
| boolean metered = false; |
| if (info != null && info.getMeteredHint()) { |
| metered = true; |
| } |
| if (config != null && config.meteredHint) { |
| metered = true; |
| } |
| if (config != null |
| && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) { |
| metered = true; |
| } |
| if (config != null |
| && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) { |
| metered = false; |
| } |
| return metered; |
| } |
| |
| /** |
| * @hide |
| * Returns true if this WiFi config is for an open network. |
| */ |
| public boolean isOpenNetwork() { |
| final int cardinality = allowedKeyManagement.cardinality(); |
| final boolean hasNoKeyMgmt = cardinality == 0 |
| || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE) |
| || allowedKeyManagement.get(KeyMgmt.OWE))); |
| |
| boolean hasNoWepKeys = true; |
| if (wepKeys != null) { |
| for (int i = 0; i < wepKeys.length; i++) { |
| if (wepKeys[i] != null) { |
| hasNoWepKeys = false; |
| break; |
| } |
| } |
| } |
| |
| return hasNoKeyMgmt && hasNoWepKeys; |
| } |
| |
| /** |
| * @hide |
| * Setting this value will force scan results associated with this configuration to |
| * be included in the bucket of networks that are externally scored. |
| * If not set, associated scan results will be treated as legacy saved networks and |
| * will take precedence over networks in the scored category. |
| */ |
| @SystemApi |
| public boolean useExternalScores; |
| |
| /** |
| * @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 |
| * Use factory MAC when connecting to this network |
| */ |
| public static final int RANDOMIZATION_NONE = 0; |
| /** |
| * @hide |
| * Generate a randomized MAC once and reuse it for all connections to this network |
| */ |
| public static final int RANDOMIZATION_PERSISTENT = 1; |
| |
| /** |
| * @hide |
| * Level of MAC randomization for this network |
| */ |
| public int macRandomizationSetting = RANDOMIZATION_PERSISTENT; |
| |
| /** |
| * @hide |
| * Randomized MAC address to use with this particular network |
| */ |
| @NonNull |
| private MacAddress mRandomizedMacAddress; |
| |
| /** |
| * @hide |
| * Checks if the given MAC address can be used for Connected Mac Randomization |
| * by verifying that it is non-null, unicast, locally assigned, and not default mac. |
| * @param mac MacAddress to check |
| * @return true if mac is good to use |
| */ |
| public static boolean isValidMacAddressForRandomization(MacAddress mac) { |
| return mac != null && !mac.isMulticastAddress() && mac.isLocallyAssigned() |
| && !MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS).equals(mac); |
| } |
| |
| /** |
| * @hide |
| * Returns Randomized MAC address to use with the network. |
| * If it is not set/valid, creates a new randomized address. |
| * If it can't generate a valid mac, returns the default MAC. |
| */ |
| public @NonNull MacAddress getOrCreateRandomizedMacAddress() { |
| int randomMacGenerationCount = 0; |
| while (!isValidMacAddressForRandomization(mRandomizedMacAddress) |
| && randomMacGenerationCount < MAXIMUM_RANDOM_MAC_GENERATION_RETRY) { |
| mRandomizedMacAddress = MacAddress.createRandomUnicastAddress(); |
| randomMacGenerationCount++; |
| } |
| |
| if (!isValidMacAddressForRandomization(mRandomizedMacAddress)) { |
| mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); |
| } |
| return mRandomizedMacAddress; |
| } |
| |
| /** |
| * Returns MAC address set to be the local randomized MAC address. |
| * Depending on user preference, the device may or may not use the returned MAC address for |
| * connections to this network. |
| * <p> |
| * Information is restricted to Device Owner, Profile Owner, and Carrier apps |
| * (which will only obtain addresses for configurations which they create). Other callers |
| * will receive a default "02:00:00:00:00:00" MAC address. |
| */ |
| public @NonNull MacAddress getRandomizedMacAddress() { |
| return mRandomizedMacAddress; |
| } |
| |
| /** |
| * @hide |
| * @param mac MacAddress to change into |
| */ |
| public void setRandomizedMacAddress(@NonNull MacAddress mac) { |
| if (mac == null) { |
| Log.e(TAG, "setRandomizedMacAddress received null MacAddress."); |
| return; |
| } |
| mRandomizedMacAddress = mac; |
| } |
| |
| /** @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 final int HOME_NETWORK_RSSI_BOOST = 5; |
| |
| /** |
| * @hide |
| * This class is used to contain all the information and API used for quality network selection |
| */ |
| public static class NetworkSelectionStatus { |
| /** |
| * Quality Network Selection Status enable, temporary disabled, permanently disabled |
| */ |
| /** |
| * This network is allowed to join Quality Network Selection |
| */ |
| public static final int NETWORK_SELECTION_ENABLED = 0; |
| /** |
| * network was temporary disabled. Can be re-enabled after a time period expire |
| */ |
| public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; |
| /** |
| * network was permanently disabled. |
| */ |
| public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; |
| /** |
| * Maximum Network selection status |
| */ |
| public static final int NETWORK_SELECTION_STATUS_MAX = 3; |
| |
| /** |
| * Quality network selection status String (for debug purpose). Use Quality network |
| * selection status value as index to extec the corresponding debug string |
| */ |
| public static final String[] QUALITY_NETWORK_SELECTION_STATUS = { |
| "NETWORK_SELECTION_ENABLED", |
| "NETWORK_SELECTION_TEMPORARY_DISABLED", |
| "NETWORK_SELECTION_PERMANENTLY_DISABLED"}; |
| |
| //Quality Network disabled reasons |
| /** |
| * Default value. Means not disabled |
| */ |
| public static final int NETWORK_SELECTION_ENABLE = 0; |
| /** |
| * The starting index for network selection disabled reasons |
| */ |
| public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1; |
| /** |
| * @deprecated it is not used any more. |
| * This network is disabled because higher layer (>2) network is bad |
| */ |
| public static final int DISABLED_BAD_LINK = 1; |
| /** |
| * This network is disabled because multiple association rejects |
| */ |
| public static final int DISABLED_ASSOCIATION_REJECTION = 2; |
| /** |
| * This network is disabled because multiple authentication failure |
| */ |
| public static final int DISABLED_AUTHENTICATION_FAILURE = 3; |
| /** |
| * This network is disabled because multiple DHCP failure |
| */ |
| public static final int DISABLED_DHCP_FAILURE = 4; |
| /** |
| * This network is disabled because of security network but no credentials |
| */ |
| public static final int DISABLED_DNS_FAILURE = 5; |
| /** |
| * This network is temporarily disabled because it has no Internet access. |
| */ |
| public static final int DISABLED_NO_INTERNET_TEMPORARY = 6; |
| /** |
| * This network is disabled because we started WPS |
| */ |
| public static final int DISABLED_WPS_START = 7; |
| /** |
| * This network is disabled because EAP-TLS failure |
| */ |
| public static final int DISABLED_TLS_VERSION_MISMATCH = 8; |
| // Values above are for temporary disablement; values below are for permanent disablement. |
| /** |
| * This network is disabled due to absence of user credentials |
| */ |
| public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 9; |
| /** |
| * This network is permanently disabled because it has no Internet access and user does not |
| * want to stay connected. |
| */ |
| public static final int DISABLED_NO_INTERNET_PERMANENT = 10; |
| /** |
| * This network is disabled due to WifiManager disable it explicitly |
| */ |
| public static final int DISABLED_BY_WIFI_MANAGER = 11; |
| /** |
| * This network is disabled due to user switching |
| */ |
| public static final int DISABLED_DUE_TO_USER_SWITCH = 12; |
| /** |
| * This network is disabled due to wrong password |
| */ |
| public static final int DISABLED_BY_WRONG_PASSWORD = 13; |
| /** |
| * This network is disabled because service is not subscribed |
| */ |
| public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 14; |
| /** |
| * This Maximum disable reason value |
| */ |
| public static final int NETWORK_SELECTION_DISABLED_MAX = 15; |
| |
| /** |
| * Quality network selection disable reason String (for debug purpose) |
| */ |
| public static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = { |
| "NETWORK_SELECTION_ENABLE", |
| "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated |
| "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ", |
| "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE", |
| "NETWORK_SELECTION_DISABLED_DHCP_FAILURE", |
| "NETWORK_SELECTION_DISABLED_DNS_FAILURE", |
| "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY", |
| "NETWORK_SELECTION_DISABLED_WPS_START", |
| "NETWORK_SELECTION_DISABLED_TLS_VERSION", |
| "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS", |
| "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT", |
| "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER", |
| "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH", |
| "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD", |
| "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION" |
| }; |
| |
| /** |
| * Invalid time stamp for network selection disable |
| */ |
| public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L; |
| |
| /** |
| * This constant indicates the current configuration has connect choice set |
| */ |
| private static final int CONNECT_CHOICE_EXISTS = 1; |
| |
| /** |
| * This constant indicates the current configuration does not have connect choice set |
| */ |
| private static final int CONNECT_CHOICE_NOT_EXISTS = -1; |
| |
| // fields for QualityNetwork Selection |
| /** |
| * Network selection status, should be in one of three status: enable, temporaily disabled |
| * or permanently disabled |
| */ |
| private int mStatus; |
| |
| /** |
| * Reason for disable this network |
| */ |
| private int mNetworkSelectionDisableReason; |
| |
| /** |
| * Last time we temporarily disabled the configuration |
| */ |
| private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; |
| |
| /** |
| * counter for each Network selection disable reason |
| */ |
| private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX]; |
| |
| /** |
| * Connect Choice over this configuration |
| * |
| * When current wifi configuration is visible to the user but user explicitly choose to |
| * connect to another network X, the another networks X's configure key will be stored here. |
| * We will consider user has a preference of X over this network. And in the future, |
| * network selection will always give X a higher preference over this configuration. |
| * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP |
| */ |
| private String mConnectChoice; |
| |
| /** |
| * The system timestamp when we records the connectChoice. This value is obtained from |
| * System.currentTimeMillis |
| */ |
| private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; |
| |
| /** |
| * Used to cache the temporary candidate during the network selection procedure. It will be |
| * kept updating once a new scan result has a higher score than current one |
| */ |
| private ScanResult mCandidate; |
| |
| /** |
| * Used to cache the score of the current temporary candidate during the network |
| * selection procedure. |
| */ |
| private int mCandidateScore; |
| |
| /** |
| * Indicate whether this network is visible in latest Qualified Network Selection. This |
| * means there is scan result found related to this Configuration and meet the minimum |
| * requirement. The saved network need not join latest Qualified Network Selection. For |
| * example, it is disabled. True means network is visible in latest Qualified Network |
| * Selection and false means network is invisible |
| */ |
| private boolean mSeenInLastQualifiedNetworkSelection; |
| |
| /** |
| * Boolean indicating if we have ever successfully connected to this network. |
| * |
| * This value will be set to true upon a successful connection. |
| * This value will be set to false if a previous value was not stored in the config or if |
| * the credentials are updated (ex. a password change). |
| */ |
| private boolean mHasEverConnected; |
| |
| /** |
| * Boolean indicating whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} |
| * chose not to connect to this network in the last qualified network selection process. |
| */ |
| private boolean mNotRecommended; |
| |
| /** |
| * Set whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not |
| * recommend connecting to this network. |
| */ |
| public void setNotRecommended(boolean notRecommended) { |
| mNotRecommended = notRecommended; |
| } |
| |
| /** |
| * Returns whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not |
| * recommend connecting to this network. |
| */ |
| public boolean isNotRecommended() { |
| return mNotRecommended; |
| } |
| |
| /** |
| * set whether this network is visible in latest Qualified Network Selection |
| * @param seen value set to candidate |
| */ |
| public void setSeenInLastQualifiedNetworkSelection(boolean seen) { |
| mSeenInLastQualifiedNetworkSelection = seen; |
| } |
| |
| /** |
| * get whether this network is visible in latest Qualified Network Selection |
| * @return returns true -- network is visible in latest Qualified Network Selection |
| * false -- network is invisible in latest Qualified Network Selection |
| */ |
| public boolean getSeenInLastQualifiedNetworkSelection() { |
| return mSeenInLastQualifiedNetworkSelection; |
| } |
| /** |
| * set the temporary candidate of current network selection procedure |
| * @param scanCandidate {@link ScanResult} the candidate set to mCandidate |
| */ |
| public void setCandidate(ScanResult scanCandidate) { |
| mCandidate = scanCandidate; |
| } |
| |
| /** |
| * get the temporary candidate of current network selection procedure |
| * @return returns {@link ScanResult} temporary candidate of current network selection |
| * procedure |
| */ |
| public ScanResult getCandidate() { |
| return mCandidate; |
| } |
| |
| /** |
| * set the score of the temporary candidate of current network selection procedure |
| * @param score value set to mCandidateScore |
| */ |
| public void setCandidateScore(int score) { |
| mCandidateScore = score; |
| } |
| |
| /** |
| * get the score of the temporary candidate of current network selection procedure |
| * @return returns score of the temporary candidate of current network selection procedure |
| */ |
| public int getCandidateScore() { |
| return mCandidateScore; |
| } |
| |
| /** |
| * get user preferred choice over this configuration |
| *@return returns configKey of user preferred choice over this configuration |
| */ |
| public String getConnectChoice() { |
| return mConnectChoice; |
| } |
| |
| /** |
| * set user preferred choice over this configuration |
| * @param newConnectChoice, the configKey of user preferred choice over this configuration |
| */ |
| public void setConnectChoice(String newConnectChoice) { |
| mConnectChoice = newConnectChoice; |
| } |
| |
| /** |
| * get the timeStamp when user select a choice over this configuration |
| * @return returns when current connectChoice is set (time from System.currentTimeMillis) |
| */ |
| public long getConnectChoiceTimestamp() { |
| return mConnectChoiceTimestamp; |
| } |
| |
| /** |
| * set the timeStamp when user select a choice over this configuration |
| * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should |
| * be obtained from System.currentTimeMillis |
| */ |
| public void setConnectChoiceTimestamp(long timeStamp) { |
| mConnectChoiceTimestamp = timeStamp; |
| } |
| |
| /** |
| * get current Quality network selection status |
| * @return returns current Quality network selection status in String (for debug purpose) |
| */ |
| public String getNetworkStatusString() { |
| return QUALITY_NETWORK_SELECTION_STATUS[mStatus]; |
| } |
| |
| public void setHasEverConnected(boolean value) { |
| mHasEverConnected = value; |
| } |
| |
| public boolean getHasEverConnected() { |
| return mHasEverConnected; |
| } |
| |
| public NetworkSelectionStatus() { |
| // previously stored configs will not have this parameter, so we default to false. |
| mHasEverConnected = false; |
| }; |
| |
| /** |
| * @param reason specific error reason |
| * @return corresponding network disable reason String (for debug purpose) |
| */ |
| public static String getNetworkDisableReasonString(int reason) { |
| if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { |
| return QUALITY_NETWORK_SELECTION_DISABLE_REASON[reason]; |
| } else { |
| return null; |
| } |
| } |
| /** |
| * get current network disable reason |
| * @return current network disable reason in String (for debug purpose) |
| */ |
| public String getNetworkDisableReasonString() { |
| return QUALITY_NETWORK_SELECTION_DISABLE_REASON[mNetworkSelectionDisableReason]; |
| } |
| |
| /** |
| * get current network network selection status |
| * @return return current network network selection status |
| */ |
| public int getNetworkSelectionStatus() { |
| return mStatus; |
| } |
| /** |
| * @return whether current network is enabled to join network selection |
| */ |
| public boolean isNetworkEnabled() { |
| return mStatus == NETWORK_SELECTION_ENABLED; |
| } |
| |
| /** |
| * @return whether current network is temporary disabled |
| */ |
| public boolean isNetworkTemporaryDisabled() { |
| return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED; |
| } |
| |
| /** |
| * @return returns whether current network is permanently disabled |
| */ |
| public boolean isNetworkPermanentlyDisabled() { |
| return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED; |
| } |
| |
| /** |
| * set current networ work selection status |
| * @param status network selection status to set |
| */ |
| public void setNetworkSelectionStatus(int status) { |
| if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) { |
| mStatus = status; |
| } |
| } |
| |
| /** |
| * @return returns current network's disable reason |
| */ |
| public int getNetworkSelectionDisableReason() { |
| return mNetworkSelectionDisableReason; |
| } |
| |
| /** |
| * set Network disable reason |
| * @param reason Network disable reason |
| */ |
| public void setNetworkSelectionDisableReason(int reason) { |
| if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) { |
| mNetworkSelectionDisableReason = reason; |
| } else { |
| throw new IllegalArgumentException("Illegal reason value: " + reason); |
| } |
| } |
| |
| /** |
| * check whether network is disabled by this reason |
| * @param reason a specific disable reason |
| * @return true -- network is disabled for this reason |
| * false -- network is not disabled for this reason |
| */ |
| public boolean isDisabledByReason(int reason) { |
| return mNetworkSelectionDisableReason == reason; |
| } |
| |
| /** |
| * @param timeStamp Set when current network is disabled in millisecond since January 1, |
| * 1970 00:00:00.0 UTC |
| */ |
| public void setDisableTime(long timeStamp) { |
| mTemporarilyDisabledTimestamp = timeStamp; |
| } |
| |
| /** |
| * @return returns when current network is disabled in millisecond since January 1, |
| * 1970 00:00:00.0 UTC |
| */ |
| public long getDisableTime() { |
| return mTemporarilyDisabledTimestamp; |
| } |
| |
| /** |
| * get the disable counter of a specific reason |
| * @param reason specific failure reason |
| * @exception throw IllegalArgumentException for illegal input |
| * @return counter number for specific error reason. |
| */ |
| public int getDisableReasonCounter(int reason) { |
| if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { |
| return mNetworkSeclectionDisableCounter[reason]; |
| } else { |
| throw new IllegalArgumentException("Illegal reason value: " + reason); |
| } |
| } |
| |
| /** |
| * set the counter of a specific failure reason |
| * @param reason reason for disable error |
| * @param value the counter value for this specific reason |
| * @exception throw IllegalArgumentException for illegal input |
| */ |
| public void setDisableReasonCounter(int reason, int value) { |
| if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { |
| mNetworkSeclectionDisableCounter[reason] = value; |
| } else { |
| throw new IllegalArgumentException("Illegal reason value: " + reason); |
| } |
| } |
| |
| /** |
| * increment the counter of a specific failure reason |
| * @param reason a specific failure reason |
| * @exception throw IllegalArgumentException for illegal input |
| */ |
| public void incrementDisableReasonCounter(int reason) { |
| if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { |
| mNetworkSeclectionDisableCounter[reason]++; |
| } else { |
| throw new IllegalArgumentException("Illegal reason value: " + reason); |
| } |
| } |
| |
| /** |
| * clear the counter of a specific failure reason |
| * @hide |
| * @param reason a specific failure reason |
| * @exception throw IllegalArgumentException for illegal input |
| */ |
| public void clearDisableReasonCounter(int reason) { |
| if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) { |
| mNetworkSeclectionDisableCounter[reason] = NETWORK_SELECTION_ENABLE; |
| } else { |
| throw new IllegalArgumentException("Illegal reason value: " + reason); |
| } |
| } |
| |
| /** |
| * clear all the failure reason counters |
| */ |
| public void clearDisableReasonCounter() { |
| Arrays.fill(mNetworkSeclectionDisableCounter, NETWORK_SELECTION_ENABLE); |
| } |
| |
| /** |
| * BSSID for connection to this network (through network selection procedure) |
| */ |
| private String mNetworkSelectionBSSID; |
| |
| /** |
| * get current network Selection BSSID |
| * @return current network Selection BSSID |
| */ |
| public String getNetworkSelectionBSSID() { |
| return mNetworkSelectionBSSID; |
| } |
| |
| /** |
| * set network Selection BSSID |
| * @param bssid The target BSSID for assocaition |
| */ |
| public void setNetworkSelectionBSSID(String bssid) { |
| mNetworkSelectionBSSID = bssid; |
| } |
| |
| public void copy(NetworkSelectionStatus source) { |
| mStatus = source.mStatus; |
| mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason; |
| for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; |
| index++) { |
| mNetworkSeclectionDisableCounter[index] = |
| source.mNetworkSeclectionDisableCounter[index]; |
| } |
| mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp; |
| mNetworkSelectionBSSID = source.mNetworkSelectionBSSID; |
| setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection()); |
| setCandidate(source.getCandidate()); |
| setCandidateScore(source.getCandidateScore()); |
| setConnectChoice(source.getConnectChoice()); |
| setConnectChoiceTimestamp(source.getConnectChoiceTimestamp()); |
| setHasEverConnected(source.getHasEverConnected()); |
| setNotRecommended(source.isNotRecommended()); |
| } |
| |
| public void writeToParcel(Parcel dest) { |
| dest.writeInt(getNetworkSelectionStatus()); |
| dest.writeInt(getNetworkSelectionDisableReason()); |
| for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; |
| index++) { |
| dest.writeInt(getDisableReasonCounter(index)); |
| } |
| dest.writeLong(getDisableTime()); |
| dest.writeString(getNetworkSelectionBSSID()); |
| if (getConnectChoice() != null) { |
| dest.writeInt(CONNECT_CHOICE_EXISTS); |
| dest.writeString(getConnectChoice()); |
| dest.writeLong(getConnectChoiceTimestamp()); |
| } else { |
| dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); |
| } |
| dest.writeInt(getHasEverConnected() ? 1 : 0); |
| dest.writeInt(isNotRecommended() ? 1 : 0); |
| } |
| |
| public void readFromParcel(Parcel in) { |
| setNetworkSelectionStatus(in.readInt()); |
| setNetworkSelectionDisableReason(in.readInt()); |
| for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX; |
| index++) { |
| setDisableReasonCounter(index, in.readInt()); |
| } |
| setDisableTime(in.readLong()); |
| setNetworkSelectionBSSID(in.readString()); |
| if (in.readInt() == CONNECT_CHOICE_EXISTS) { |
| setConnectChoice(in.readString()); |
| setConnectChoiceTimestamp(in.readLong()); |
| } else { |
| setConnectChoice(null); |
| setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); |
| } |
| setHasEverConnected(in.readInt() != 0); |
| setNotRecommended(in.readInt() != 0); |
| } |
| } |
| |
| /** |
| * @hide |
| * network selection related member |
| */ |
| private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus(); |
| |
| /** |
| * @hide |
| * This class is intended to store extra failure reason information for the most recent |
| * connection attempt, so that it may be surfaced to the settings UI |
| */ |
| public static class RecentFailure { |
| |
| /** |
| * No recent failure, or no specific reason given for the recent connection failure |
| */ |
| public static final int NONE = 0; |
| /** |
| * Connection to this network recently failed due to Association Rejection Status 17 |
| * (AP is full) |
| */ |
| public static final int STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17; |
| /** |
| * Association Rejection Status code (NONE for success/non-association-rejection-fail) |
| */ |
| private int mAssociationStatus = NONE; |
| |
| /** |
| * @param status the association status code for the recent failure |
| */ |
| public void setAssociationStatus(int status) { |
| mAssociationStatus = status; |
| } |
| /** |
| * Sets the RecentFailure to NONE |
| */ |
| public void clear() { |
| mAssociationStatus = NONE; |
| } |
| /** |
| * Get the recent failure code |
| */ |
| public int getAssociationStatus() { |
| return mAssociationStatus; |
| } |
| } |
| |
| /** |
| * @hide |
| * RecentFailure member |
| */ |
| final public RecentFailure recentFailure = new RecentFailure(); |
| |
| /** |
| * @hide |
| * @return network selection status |
| */ |
| public NetworkSelectionStatus getNetworkSelectionStatus() { |
| return mNetworkSelectionStatus; |
| } |
| |
| /** |
| * Set the network selection status |
| * @hide |
| */ |
| public void setNetworkSelectionStatus(NetworkSelectionStatus status) { |
| mNetworkSelectionStatus = status; |
| } |
| |
| /** |
| * @hide |
| * Linked Configurations: represent the set of Wificonfigurations that are equivalent |
| * regarding roaming and auto-joining. |
| * The linked configuration may or may not have same SSID, and may or may not have same |
| * credentials. |
| * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server. |
| */ |
| public HashMap<String, Integer> linkedConfigurations; |
| |
| public WifiConfiguration() { |
| networkId = INVALID_NETWORK_ID; |
| SSID = null; |
| BSSID = null; |
| FQDN = null; |
| roamingConsortiumIds = new long[0]; |
| priority = 0; |
| hiddenSSID = false; |
| allowedKeyManagement = new BitSet(); |
| allowedProtocols = new BitSet(); |
| allowedAuthAlgorithms = new BitSet(); |
| allowedPairwiseCiphers = new BitSet(); |
| allowedGroupCiphers = new BitSet(); |
| allowedGroupManagementCiphers = new BitSet(); |
| allowedSuiteBCiphers = new BitSet(); |
| wepKeys = new String[4]; |
| for (int i = 0; i < wepKeys.length; i++) { |
| wepKeys[i] = null; |
| } |
| enterpriseConfig = new WifiEnterpriseConfig(); |
| selfAdded = false; |
| didSelfAdd = false; |
| ephemeral = false; |
| osu = false; |
| trusted = true; // Networks are considered trusted by default. |
| fromWifiNetworkSuggestion = false; |
| fromWifiNetworkSpecifier = false; |
| meteredHint = false; |
| meteredOverride = METERED_OVERRIDE_NONE; |
| useExternalScores = false; |
| validatedInternetAccess = false; |
| mIpConfiguration = new IpConfiguration(); |
| lastUpdateUid = -1; |
| creatorUid = -1; |
| shared = true; |
| dtimInterval = 0; |
| mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS); |
| } |
| |
| /** |
| * Identify if this configuration represents a Passpoint network |
| */ |
| public boolean isPasspoint() { |
| return !TextUtils.isEmpty(FQDN) |
| && !TextUtils.isEmpty(providerFriendlyName) |
| && enterpriseConfig != null |
| && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; |
| } |
| |
| /** |
| * Helper function, identify if a configuration is linked |
| * @hide |
| */ |
| public boolean isLinked(WifiConfiguration config) { |
| if (config != null) { |
| if (config.linkedConfigurations != null && linkedConfigurations != null) { |
| if (config.linkedConfigurations.get(configKey()) != null |
| && linkedConfigurations.get(config.configKey()) != null) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Helper function, idenfity if a configuration should be treated as an enterprise network |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public boolean isEnterprise() { |
| return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) |
| || allowedKeyManagement.get(KeyMgmt.IEEE8021X) |
| || allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) |
| && enterpriseConfig != null |
| && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder sbuf = new StringBuilder(); |
| if (this.status == WifiConfiguration.Status.CURRENT) { |
| sbuf.append("* "); |
| } else if (this.status == WifiConfiguration.Status.DISABLED) { |
| sbuf.append("- DSBLE "); |
| } |
| sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID). |
| append(" PROVIDER-NAME: ").append(this.providerFriendlyName). |
| append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN) |
| .append(" PRIO: ").append(this.priority) |
| .append(" HIDDEN: ").append(this.hiddenSSID) |
| .append(" PMF: ").append(this.requirePMF) |
| .append('\n'); |
| |
| |
| sbuf.append(" NetworkSelectionStatus ") |
| .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n"); |
| if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) { |
| sbuf.append(" mNetworkSelectionDisableReason ") |
| .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n"); |
| |
| for (int index = mNetworkSelectionStatus.NETWORK_SELECTION_ENABLE; |
| index < mNetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) { |
| if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) { |
| sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index) |
| + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index) |
| + "\n"); |
| } |
| } |
| } |
| if (mNetworkSelectionStatus.getConnectChoice() != null) { |
| sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); |
| sbuf.append(" connect choice set time: ") |
| .append(TimeUtils.logTimeOfDay( |
| mNetworkSelectionStatus.getConnectChoiceTimestamp())); |
| } |
| sbuf.append(" hasEverConnected: ") |
| .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n"); |
| |
| if (this.numAssociation > 0) { |
| sbuf.append(" numAssociation ").append(this.numAssociation).append("\n"); |
| } |
| if (this.numNoInternetAccessReports > 0) { |
| sbuf.append(" numNoInternetAccessReports "); |
| sbuf.append(this.numNoInternetAccessReports).append("\n"); |
| } |
| if (this.updateTime != null) { |
| sbuf.append(" update ").append(this.updateTime).append("\n"); |
| } |
| if (this.creationTime != null) { |
| sbuf.append(" creation ").append(this.creationTime).append("\n"); |
| } |
| if (this.didSelfAdd) sbuf.append(" didSelfAdd"); |
| if (this.selfAdded) sbuf.append(" selfAdded"); |
| if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess"); |
| if (this.ephemeral) sbuf.append(" ephemeral"); |
| if (this.osu) sbuf.append(" osu"); |
| if (this.trusted) sbuf.append(" trusted"); |
| if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion"); |
| if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier"); |
| if (this.meteredHint) sbuf.append(" meteredHint"); |
| if (this.useExternalScores) sbuf.append(" useExternalScores"); |
| if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess |
| || this.ephemeral || this.trusted || this.fromWifiNetworkSuggestion |
| || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) { |
| sbuf.append("\n"); |
| } |
| if (this.meteredOverride != METERED_OVERRIDE_NONE) { |
| sbuf.append(" meteredOverride ").append(meteredOverride).append("\n"); |
| } |
| sbuf.append(" macRandomizationSetting ").append(macRandomizationSetting).append("\n"); |
| sbuf.append(" KeyMgmt:"); |
| for (int k = 0; k < this.allowedKeyManagement.size(); k++) { |
| if (this.allowedKeyManagement.get(k)) { |
| sbuf.append(" "); |
| if (k < KeyMgmt.strings.length) { |
| sbuf.append(KeyMgmt.strings[k]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append(" Protocols:"); |
| for (int p = 0; p < this.allowedProtocols.size(); p++) { |
| if (this.allowedProtocols.get(p)) { |
| sbuf.append(" "); |
| if (p < Protocol.strings.length) { |
| sbuf.append(Protocol.strings[p]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append('\n'); |
| sbuf.append(" AuthAlgorithms:"); |
| for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) { |
| if (this.allowedAuthAlgorithms.get(a)) { |
| sbuf.append(" "); |
| if (a < AuthAlgorithm.strings.length) { |
| sbuf.append(AuthAlgorithm.strings[a]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append('\n'); |
| sbuf.append(" PairwiseCiphers:"); |
| for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) { |
| if (this.allowedPairwiseCiphers.get(pc)) { |
| sbuf.append(" "); |
| if (pc < PairwiseCipher.strings.length) { |
| sbuf.append(PairwiseCipher.strings[pc]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append('\n'); |
| sbuf.append(" GroupCiphers:"); |
| for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) { |
| if (this.allowedGroupCiphers.get(gc)) { |
| sbuf.append(" "); |
| if (gc < GroupCipher.strings.length) { |
| sbuf.append(GroupCipher.strings[gc]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append('\n'); |
| sbuf.append(" GroupMgmtCiphers:"); |
| for (int gmc = 0; gmc < this.allowedGroupManagementCiphers.size(); gmc++) { |
| if (this.allowedGroupManagementCiphers.get(gmc)) { |
| sbuf.append(" "); |
| if (gmc < GroupMgmtCipher.strings.length) { |
| sbuf.append(GroupMgmtCipher.strings[gmc]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append('\n'); |
| sbuf.append(" SuiteBCiphers:"); |
| for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) { |
| if (this.allowedSuiteBCiphers.get(sbc)) { |
| sbuf.append(" "); |
| if (sbc < SuiteBCipher.strings.length) { |
| sbuf.append(SuiteBCipher.strings[sbc]); |
| } else { |
| sbuf.append("??"); |
| } |
| } |
| } |
| sbuf.append('\n').append(" PSK/SAE: "); |
| if (this.preSharedKey != null) { |
| sbuf.append('*'); |
| } |
| |
| sbuf.append("\nEnterprise config:\n"); |
| sbuf.append(enterpriseConfig); |
| |
| sbuf.append("IP config:\n"); |
| sbuf.append(mIpConfiguration.toString()); |
| |
| if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) { |
| sbuf.append(" networkSelectionBSSID=" |
| + mNetworkSelectionStatus.getNetworkSelectionBSSID()); |
| } |
| long now_ms = SystemClock.elapsedRealtime(); |
| if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus |
| .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) { |
| sbuf.append('\n'); |
| long diff = now_ms - mNetworkSelectionStatus.getDisableTime(); |
| if (diff <= 0) { |
| sbuf.append(" blackListed since <incorrect>"); |
| } else { |
| sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec "); |
| } |
| } |
| if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid); |
| if (creatorName != null) sbuf.append(" cname=" + creatorName); |
| if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid); |
| if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName); |
| if (updateIdentifier != null) sbuf.append(" updateIdentifier=" + updateIdentifier); |
| sbuf.append(" lcuid=" + lastConnectUid); |
| sbuf.append(" userApproved=" + userApprovedAsString(userApproved)); |
| sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected); |
| sbuf.append(" "); |
| |
| if (this.lastConnected != 0) { |
| sbuf.append('\n'); |
| sbuf.append("lastConnected: ").append(TimeUtils.logTimeOfDay(this.lastConnected)); |
| sbuf.append(" "); |
| } |
| sbuf.append('\n'); |
| if (this.linkedConfigurations != null) { |
| for (String key : this.linkedConfigurations.keySet()) { |
| sbuf.append(" linked: ").append(key); |
| sbuf.append('\n'); |
| } |
| } |
| sbuf.append("recentFailure: ").append("Association Rejection code: ") |
| .append(recentFailure.getAssociationStatus()).append("\n"); |
| return sbuf.toString(); |
| } |
| |
| /** {@hide} */ |
| @UnsupportedAppUsage |
| public String getPrintableSsid() { |
| if (SSID == null) return ""; |
| final int length = SSID.length(); |
| if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') { |
| return SSID.substring(1, length - 1); |
| } |
| |
| /** The ascii-encoded string format is P"<ascii-encoded-string>" |
| * The decoding is implemented in the supplicant for a newly configured |
| * network. |
| */ |
| if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') && |
| (SSID.charAt(length-1) == '"')) { |
| WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded( |
| SSID.substring(2, length - 1)); |
| return wifiSsid.toString(); |
| } |
| return SSID; |
| } |
| |
| /** @hide **/ |
| public static String userApprovedAsString(int userApproved) { |
| switch (userApproved) { |
| case USER_APPROVED: |
| return "USER_APPROVED"; |
| case USER_BANNED: |
| return "USER_BANNED"; |
| case USER_UNSPECIFIED: |
| return "USER_UNSPECIFIED"; |
| default: |
| return "INVALID"; |
| } |
| } |
| |
| /** |
| * Get an identifier for associating credentials with this config |
| * @param current configuration contains values for additional fields |
| * that are not part of this configuration. Used |
| * when a config with some fields is passed by an application. |
| * @throws IllegalStateException if config is invalid for key id generation |
| * @hide |
| */ |
| public String getKeyIdForCredentials(WifiConfiguration current) { |
| String keyMgmt = null; |
| |
| try { |
| // Get current config details for fields that are not initialized |
| if (TextUtils.isEmpty(SSID)) SSID = current.SSID; |
| if (allowedKeyManagement.cardinality() == 0) { |
| allowedKeyManagement = current.allowedKeyManagement; |
| } |
| if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { |
| keyMgmt = KeyMgmt.strings[KeyMgmt.WPA_EAP]; |
| } |
| if (allowedKeyManagement.get(KeyMgmt.OSEN)) { |
| keyMgmt = KeyMgmt.strings[KeyMgmt.OSEN]; |
| } |
| if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { |
| keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X]; |
| } |
| |
| if (TextUtils.isEmpty(keyMgmt)) { |
| throw new IllegalStateException("Not an EAP network"); |
| } |
| |
| return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" + |
| trimStringForKeyId(enterpriseConfig.getKeyId(current != null ? |
| current.enterpriseConfig : null)); |
| } catch (NullPointerException e) { |
| throw new IllegalStateException("Invalid config details"); |
| } |
| } |
| |
| private String trimStringForKeyId(String string) { |
| // Remove quotes and spaces |
| return string.replace("\"", "").replace(" ", ""); |
| } |
| |
| private static BitSet readBitSet(Parcel src) { |
| int cardinality = src.readInt(); |
| |
| BitSet set = new BitSet(); |
| for (int i = 0; i < cardinality; i++) { |
| set.set(src.readInt()); |
| } |
| |
| return set; |
| } |
| |
| private static void writeBitSet(Parcel dest, BitSet set) { |
| int nextSetBit = -1; |
| |
| dest.writeInt(set.cardinality()); |
| |
| while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { |
| dest.writeInt(nextSetBit); |
| } |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public int getAuthType() { |
| if (allowedKeyManagement.cardinality() > 1) { |
| throw new IllegalStateException("More than one auth type set"); |
| } |
| if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { |
| return KeyMgmt.WPA_PSK; |
| } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { |
| return KeyMgmt.WPA2_PSK; |
| } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { |
| return KeyMgmt.WPA_EAP; |
| } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { |
| return KeyMgmt.IEEE8021X; |
| } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { |
| return KeyMgmt.SAE; |
| } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { |
| return KeyMgmt.OWE; |
| } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { |
| return KeyMgmt.SUITE_B_192; |
| } |
| return KeyMgmt.NONE; |
| } |
| |
| /* @hide |
| * Cache the config key, this seems useful as a speed up since a lot of |
| * lookups in the config store are done and based on this key. |
| */ |
| String mCachedConfigKey; |
| |
| /** @hide |
| * return the string used to calculate the hash in WifiConfigStore |
| * and uniquely identify this WifiConfiguration |
| */ |
| public String configKey(boolean allowCached) { |
| String key; |
| if (allowCached && mCachedConfigKey != null) { |
| key = mCachedConfigKey; |
| } else if (providerFriendlyName != null) { |
| key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP]; |
| if (!shared) { |
| key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); |
| } |
| } else { |
| if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { |
| key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; |
| } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) || |
| allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { |
| key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; |
| } else if (wepKeys[0] != null) { |
| key = SSID + "WEP"; |
| } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { |
| key = SSID + KeyMgmt.strings[KeyMgmt.OWE]; |
| } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { |
| key = SSID + KeyMgmt.strings[KeyMgmt.SAE]; |
| } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { |
| key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192]; |
| } else { |
| key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; |
| } |
| if (!shared) { |
| key += "-" + Integer.toString(UserHandle.getUserId(creatorUid)); |
| } |
| mCachedConfigKey = key; |
| } |
| return key; |
| } |
| |
| /** @hide |
| * get configKey, force calculating the config string |
| */ |
| public String configKey() { |
| return configKey(false); |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public IpConfiguration getIpConfiguration() { |
| return mIpConfiguration; |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void setIpConfiguration(IpConfiguration ipConfiguration) { |
| if (ipConfiguration == null) ipConfiguration = new IpConfiguration(); |
| mIpConfiguration = ipConfiguration; |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public StaticIpConfiguration getStaticIpConfiguration() { |
| return mIpConfiguration.getStaticIpConfiguration(); |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) { |
| mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration); |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public IpConfiguration.IpAssignment getIpAssignment() { |
| return mIpConfiguration.ipAssignment; |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) { |
| mIpConfiguration.ipAssignment = ipAssignment; |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public IpConfiguration.ProxySettings getProxySettings() { |
| return mIpConfiguration.proxySettings; |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void setProxySettings(IpConfiguration.ProxySettings proxySettings) { |
| mIpConfiguration.proxySettings = proxySettings; |
| } |
| |
| /** |
| * Returns the HTTP proxy used by this object. |
| * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this |
| * WifiConfiguration, or {@code null} if no proxy is specified. |
| */ |
| public ProxyInfo getHttpProxy() { |
| if (mIpConfiguration.proxySettings == IpConfiguration.ProxySettings.NONE) { |
| return null; |
| } |
| return new ProxyInfo(mIpConfiguration.httpProxy); |
| } |
| |
| /** |
| * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a |
| * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration} |
| * with modified proxy settings, the methods {@link WifiManager#addNetwork} and |
| * {@link WifiManager#updateNetwork} fail and return {@code -1}. |
| * |
| * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this |
| * WifiConfiguration. Setting this to {@code null} will explicitly set no |
| * proxy, removing any proxy that was previously set. |
| * @exception IllegalArgumentException for invalid httpProxy |
| */ |
| public void setHttpProxy(ProxyInfo httpProxy) { |
| if (httpProxy == null) { |
| mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE); |
| mIpConfiguration.setHttpProxy(null); |
| return; |
| } |
| ProxyInfo httpProxyCopy; |
| ProxySettings proxySettingCopy; |
| if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) { |
| proxySettingCopy = IpConfiguration.ProxySettings.PAC; |
| // Construct a new PAC URL Proxy |
| httpProxyCopy = new ProxyInfo(httpProxy.getPacFileUrl(), httpProxy.getPort()); |
| } else { |
| proxySettingCopy = IpConfiguration.ProxySettings.STATIC; |
| // Construct a new HTTP Proxy |
| httpProxyCopy = new ProxyInfo(httpProxy.getHost(), httpProxy.getPort(), |
| httpProxy.getExclusionListAsString()); |
| } |
| if (!httpProxyCopy.isValid()) { |
| throw new IllegalArgumentException("Invalid ProxyInfo: " + httpProxyCopy.toString()); |
| } |
| mIpConfiguration.setProxySettings(proxySettingCopy); |
| mIpConfiguration.setHttpProxy(httpProxyCopy); |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void setProxy(ProxySettings settings, ProxyInfo proxy) { |
| mIpConfiguration.proxySettings = settings; |
| mIpConfiguration.httpProxy = proxy; |
| } |
| |
| /** Implement the Parcelable interface {@hide} */ |
| public int describeContents() { |
| return 0; |
| } |
| |
| /** @hide */ |
| public void setPasspointManagementObjectTree(String passpointManagementObjectTree) { |
| mPasspointManagementObjectTree = passpointManagementObjectTree; |
| } |
| |
| /** @hide */ |
| public String getMoTree() { |
| return mPasspointManagementObjectTree; |
| } |
| |
| /** copy constructor {@hide} */ |
| @UnsupportedAppUsage |
| public WifiConfiguration(WifiConfiguration source) { |
| if (source != null) { |
| networkId = source.networkId; |
| status = source.status; |
| SSID = source.SSID; |
| BSSID = source.BSSID; |
| FQDN = source.FQDN; |
| roamingConsortiumIds = source.roamingConsortiumIds.clone(); |
| providerFriendlyName = source.providerFriendlyName; |
| isHomeProviderNetwork = source.isHomeProviderNetwork; |
| preSharedKey = source.preSharedKey; |
| |
| mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus()); |
| apBand = source.apBand; |
| apChannel = source.apChannel; |
| |
| wepKeys = new String[4]; |
| for (int i = 0; i < wepKeys.length; i++) { |
| wepKeys[i] = source.wepKeys[i]; |
| } |
| |
| wepTxKeyIndex = source.wepTxKeyIndex; |
| priority = source.priority; |
| hiddenSSID = source.hiddenSSID; |
| allowedKeyManagement = (BitSet) source.allowedKeyManagement.clone(); |
| allowedProtocols = (BitSet) source.allowedProtocols.clone(); |
| allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); |
| allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); |
| allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); |
| allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone(); |
| allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone(); |
| enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); |
| |
| defaultGwMacAddress = source.defaultGwMacAddress; |
| |
| mIpConfiguration = new IpConfiguration(source.mIpConfiguration); |
| |
| if ((source.linkedConfigurations != null) |
| && (source.linkedConfigurations.size() > 0)) { |
| linkedConfigurations = new HashMap<String, Integer>(); |
| linkedConfigurations.putAll(source.linkedConfigurations); |
| } |
| mCachedConfigKey = null; //force null configKey |
| selfAdded = source.selfAdded; |
| validatedInternetAccess = source.validatedInternetAccess; |
| isLegacyPasspointConfig = source.isLegacyPasspointConfig; |
| ephemeral = source.ephemeral; |
| osu = source.osu; |
| trusted = source.trusted; |
| fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion; |
| fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier; |
| meteredHint = source.meteredHint; |
| meteredOverride = source.meteredOverride; |
| useExternalScores = source.useExternalScores; |
| |
| didSelfAdd = source.didSelfAdd; |
| lastConnectUid = source.lastConnectUid; |
| lastUpdateUid = source.lastUpdateUid; |
| creatorUid = source.creatorUid; |
| creatorName = source.creatorName; |
| lastUpdateName = source.lastUpdateName; |
| peerWifiConfiguration = source.peerWifiConfiguration; |
| |
| lastConnected = source.lastConnected; |
| lastDisconnected = source.lastDisconnected; |
| numScorerOverride = source.numScorerOverride; |
| numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; |
| numAssociation = source.numAssociation; |
| userApproved = source.userApproved; |
| numNoInternetAccessReports = source.numNoInternetAccessReports; |
| noInternetAccessExpected = source.noInternetAccessExpected; |
| creationTime = source.creationTime; |
| updateTime = source.updateTime; |
| shared = source.shared; |
| recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus()); |
| mRandomizedMacAddress = source.mRandomizedMacAddress; |
| macRandomizationSetting = source.macRandomizationSetting; |
| requirePMF = source.requirePMF; |
| updateIdentifier = source.updateIdentifier; |
| } |
| } |
| |
| /** Implement the Parcelable interface {@hide} */ |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| dest.writeInt(networkId); |
| dest.writeInt(status); |
| mNetworkSelectionStatus.writeToParcel(dest); |
| dest.writeString(SSID); |
| dest.writeString(BSSID); |
| dest.writeInt(apBand); |
| dest.writeInt(apChannel); |
| dest.writeString(FQDN); |
| dest.writeString(providerFriendlyName); |
| dest.writeInt(isHomeProviderNetwork ? 1 : 0); |
| dest.writeInt(roamingConsortiumIds.length); |
| for (long roamingConsortiumId : roamingConsortiumIds) { |
| dest.writeLong(roamingConsortiumId); |
| } |
| dest.writeString(preSharedKey); |
| for (String wepKey : wepKeys) { |
| dest.writeString(wepKey); |
| } |
| dest.writeInt(wepTxKeyIndex); |
| dest.writeInt(priority); |
| dest.writeInt(hiddenSSID ? 1 : 0); |
| dest.writeInt(requirePMF ? 1 : 0); |
| dest.writeString(updateIdentifier); |
| |
| writeBitSet(dest, allowedKeyManagement); |
| writeBitSet(dest, allowedProtocols); |
| writeBitSet(dest, allowedAuthAlgorithms); |
| writeBitSet(dest, allowedPairwiseCiphers); |
| writeBitSet(dest, allowedGroupCiphers); |
| writeBitSet(dest, allowedGroupManagementCiphers); |
| writeBitSet(dest, allowedSuiteBCiphers); |
| |
| dest.writeParcelable(enterpriseConfig, flags); |
| |
| dest.writeParcelable(mIpConfiguration, flags); |
| dest.writeString(dhcpServer); |
| dest.writeString(defaultGwMacAddress); |
| dest.writeInt(selfAdded ? 1 : 0); |
| dest.writeInt(didSelfAdd ? 1 : 0); |
| dest.writeInt(validatedInternetAccess ? 1 : 0); |
| dest.writeInt(isLegacyPasspointConfig ? 1 : 0); |
| dest.writeInt(ephemeral ? 1 : 0); |
| dest.writeInt(trusted ? 1 : 0); |
| dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0); |
| dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0); |
| dest.writeInt(meteredHint ? 1 : 0); |
| dest.writeInt(meteredOverride); |
| dest.writeInt(useExternalScores ? 1 : 0); |
| dest.writeInt(creatorUid); |
| dest.writeInt(lastConnectUid); |
| dest.writeInt(lastUpdateUid); |
| dest.writeString(creatorName); |
| dest.writeString(lastUpdateName); |
| dest.writeInt(numScorerOverride); |
| dest.writeInt(numScorerOverrideAndSwitchedNetwork); |
| dest.writeInt(numAssociation); |
| dest.writeInt(userApproved); |
| dest.writeInt(numNoInternetAccessReports); |
| dest.writeInt(noInternetAccessExpected ? 1 : 0); |
| dest.writeInt(shared ? 1 : 0); |
| dest.writeString(mPasspointManagementObjectTree); |
| dest.writeInt(recentFailure.getAssociationStatus()); |
| dest.writeParcelable(mRandomizedMacAddress, flags); |
| dest.writeInt(macRandomizationSetting); |
| dest.writeInt(osu ? 1 : 0); |
| } |
| |
| /** Implement the Parcelable interface {@hide} */ |
| @UnsupportedAppUsage |
| public static final @android.annotation.NonNull Creator<WifiConfiguration> CREATOR = |
| new Creator<WifiConfiguration>() { |
| public WifiConfiguration createFromParcel(Parcel in) { |
| WifiConfiguration config = new WifiConfiguration(); |
| config.networkId = in.readInt(); |
| config.status = in.readInt(); |
| config.mNetworkSelectionStatus.readFromParcel(in); |
| config.SSID = in.readString(); |
| config.BSSID = in.readString(); |
| config.apBand = in.readInt(); |
| config.apChannel = in.readInt(); |
| config.FQDN = in.readString(); |
| config.providerFriendlyName = in.readString(); |
| config.isHomeProviderNetwork = in.readInt() != 0; |
| int numRoamingConsortiumIds = in.readInt(); |
| config.roamingConsortiumIds = new long[numRoamingConsortiumIds]; |
| for (int i = 0; i < numRoamingConsortiumIds; i++) { |
| config.roamingConsortiumIds[i] = in.readLong(); |
| } |
| config.preSharedKey = in.readString(); |
| for (int i = 0; i < config.wepKeys.length; i++) { |
| config.wepKeys[i] = in.readString(); |
| } |
| config.wepTxKeyIndex = in.readInt(); |
| config.priority = in.readInt(); |
| config.hiddenSSID = in.readInt() != 0; |
| config.requirePMF = in.readInt() != 0; |
| config.updateIdentifier = in.readString(); |
| |
| config.allowedKeyManagement = readBitSet(in); |
| config.allowedProtocols = readBitSet(in); |
| config.allowedAuthAlgorithms = readBitSet(in); |
| config.allowedPairwiseCiphers = readBitSet(in); |
| config.allowedGroupCiphers = readBitSet(in); |
| config.allowedGroupManagementCiphers = readBitSet(in); |
| config.allowedSuiteBCiphers = readBitSet(in); |
| |
| config.enterpriseConfig = in.readParcelable(null); |
| config.setIpConfiguration(in.readParcelable(null)); |
| config.dhcpServer = in.readString(); |
| config.defaultGwMacAddress = in.readString(); |
| config.selfAdded = in.readInt() != 0; |
| config.didSelfAdd = in.readInt() != 0; |
| config.validatedInternetAccess = in.readInt() != 0; |
| config.isLegacyPasspointConfig = in.readInt() != 0; |
| config.ephemeral = in.readInt() != 0; |
| config.trusted = in.readInt() != 0; |
| config.fromWifiNetworkSuggestion = in.readInt() != 0; |
| config.fromWifiNetworkSpecifier = in.readInt() != 0; |
| config.meteredHint = in.readInt() != 0; |
| config.meteredOverride = in.readInt(); |
| config.useExternalScores = in.readInt() != 0; |
| config.creatorUid = in.readInt(); |
| config.lastConnectUid = in.readInt(); |
| config.lastUpdateUid = in.readInt(); |
| config.creatorName = in.readString(); |
| config.lastUpdateName = in.readString(); |
| config.numScorerOverride = in.readInt(); |
| config.numScorerOverrideAndSwitchedNetwork = in.readInt(); |
| config.numAssociation = in.readInt(); |
| config.userApproved = in.readInt(); |
| config.numNoInternetAccessReports = in.readInt(); |
| config.noInternetAccessExpected = in.readInt() != 0; |
| config.shared = in.readInt() != 0; |
| config.mPasspointManagementObjectTree = in.readString(); |
| config.recentFailure.setAssociationStatus(in.readInt()); |
| config.mRandomizedMacAddress = in.readParcelable(null); |
| config.macRandomizationSetting = in.readInt(); |
| config.osu = in.readInt() != 0; |
| return config; |
| } |
| |
| public WifiConfiguration[] newArray(int size) { |
| return new WifiConfiguration[size]; |
| } |
| }; |
| |
| /** |
| * Serializes the object for backup |
| * @hide |
| */ |
| public byte[] getBytesForBackup() throws IOException { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| DataOutputStream out = new DataOutputStream(baos); |
| |
| out.writeInt(BACKUP_VERSION); |
| BackupUtils.writeString(out, SSID); |
| out.writeInt(apBand); |
| out.writeInt(apChannel); |
| BackupUtils.writeString(out, preSharedKey); |
| out.writeInt(getAuthType()); |
| out.writeBoolean(hiddenSSID); |
| return baos.toByteArray(); |
| } |
| |
| /** |
| * Deserializes a byte array into the WiFiConfiguration Object |
| * @hide |
| */ |
| public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException, |
| BackupUtils.BadVersionException { |
| WifiConfiguration config = new WifiConfiguration(); |
| int version = in.readInt(); |
| if (version < 1 || version > BACKUP_VERSION) { |
| throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); |
| } |
| |
| if (version == 1) return null; // Version 1 is a bad dataset. |
| |
| config.SSID = BackupUtils.readString(in); |
| config.apBand = in.readInt(); |
| config.apChannel = in.readInt(); |
| config.preSharedKey = BackupUtils.readString(in); |
| config.allowedKeyManagement.set(in.readInt()); |
| if (version >= 3) { |
| config.hiddenSSID = in.readBoolean(); |
| } |
| return config; |
| } |
| } |