blob: 5d130c6b4dcc6d93e478d82561b4e635d3797770 [file] [log] [blame]
/*
* 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.os.Parcelable;
import android.os.Parcel;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkUtils;
import android.text.TextUtils;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.EnumMap;
import java.util.Locale;
/**
* Describes the state of any Wifi connection that is active or
* is in the process of being set up.
*/
public class WifiInfo implements Parcelable {
private static final String TAG = "WifiInfo";
/**
* This is the map described in the Javadoc comment above. The positions
* of the elements of the array must correspond to the ordinal values
* of <code>DetailedState</code>.
*/
private static final EnumMap<SupplicantState, DetailedState> stateMap =
new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);
static {
stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR);
stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE);
stateMap.put(SupplicantState.INVALID, DetailedState.FAILED);
}
private SupplicantState mSupplicantState;
private String mBSSID;
private WifiSsid mWifiSsid;
private int mNetworkId;
private boolean mHiddenSSID;
/** Received Signal Strength Indicator */
private int mRssi;
/** Link speed in Mbps */
public static final String LINK_SPEED_UNITS = "Mbps";
private int mLinkSpeed;
private InetAddress mIpAddress;
private String mMacAddress;
/**
* Flag indicating that AP has hinted that upstream connection is metered,
* and sensitive to heavy data transfers.
*/
private boolean mMeteredHint;
WifiInfo() {
mWifiSsid = null;
mBSSID = null;
mNetworkId = -1;
mSupplicantState = SupplicantState.UNINITIALIZED;
mRssi = -9999;
mLinkSpeed = -1;
mHiddenSSID = false;
}
/**
* Copy constructor
* @hide
*/
public WifiInfo(WifiInfo source) {
if (source != null) {
mSupplicantState = source.mSupplicantState;
mBSSID = source.mBSSID;
mWifiSsid = source.mWifiSsid;
mNetworkId = source.mNetworkId;
mHiddenSSID = source.mHiddenSSID;
mRssi = source.mRssi;
mLinkSpeed = source.mLinkSpeed;
mIpAddress = source.mIpAddress;
mMacAddress = source.mMacAddress;
mMeteredHint = source.mMeteredHint;
}
}
void setSSID(WifiSsid wifiSsid) {
mWifiSsid = wifiSsid;
// network is considered not hidden by default
mHiddenSSID = false;
}
/**
* Returns the service set identifier (SSID) of the current 802.11 network.
* If the SSID can be decoded as UTF-8, it will be returned surrounded by double
* quotation marks. Otherwise, it is returned as a string of hex digits. The
* SSID may be {@code null} if there is no network currently connected.
* @return the SSID
*/
public String getSSID() {
if (mWifiSsid != null) {
String unicode = mWifiSsid.toString();
if (!TextUtils.isEmpty(unicode)) {
return "\"" + unicode + "\"";
} else {
return mWifiSsid.getHexString();
}
}
return WifiSsid.NONE;
}
/** @hide */
public WifiSsid getWifiSsid() {
return mWifiSsid;
}
void setBSSID(String BSSID) {
mBSSID = BSSID;
}
/**
* Return the basic service set identifier (BSSID) of the current access point.
* The BSSID may be {@code null} if there is no network currently connected.
* @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
*/
public String getBSSID() {
return mBSSID;
}
/**
* Returns the received signal strength indicator of the current 802.11
* network.
* <p><strong>This is not normalized, but should be!</strong></p>
* @return the RSSI, in the range ??? to ???
*/
public int getRssi() {
return mRssi;
}
void setRssi(int rssi) {
mRssi = rssi;
}
/**
* Returns the current link speed in {@link #LINK_SPEED_UNITS}.
* @return the link speed.
* @see #LINK_SPEED_UNITS
*/
public int getLinkSpeed() {
return mLinkSpeed;
}
void setLinkSpeed(int linkSpeed) {
this.mLinkSpeed = linkSpeed;
}
/**
* Record the MAC address of the WLAN interface
* @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
*/
void setMacAddress(String macAddress) {
this.mMacAddress = macAddress;
}
public String getMacAddress() {
return mMacAddress;
}
/** {@hide} */
public void setMeteredHint(boolean meteredHint) {
mMeteredHint = meteredHint;
}
/** {@hide} */
public boolean getMeteredHint() {
return mMeteredHint;
}
void setNetworkId(int id) {
mNetworkId = id;
}
/**
* Each configured network has a unique small integer ID, used to identify
* the network when performing operations on the supplicant. This method
* returns the ID for the currently connected network.
* @return the network ID, or -1 if there is no currently connected network
*/
public int getNetworkId() {
return mNetworkId;
}
/**
* Return the detailed state of the supplicant's negotiation with an
* access point, in the form of a {@link SupplicantState SupplicantState} object.
* @return the current {@link SupplicantState SupplicantState}
*/
public SupplicantState getSupplicantState() {
return mSupplicantState;
}
void setSupplicantState(SupplicantState state) {
mSupplicantState = state;
}
void setInetAddress(InetAddress address) {
mIpAddress = address;
}
public int getIpAddress() {
int result = 0;
if (mIpAddress instanceof Inet4Address) {
result = NetworkUtils.inetAddressToInt((Inet4Address)mIpAddress);
}
return result;
}
/**
* @return {@code true} if this network does not broadcast its SSID, so an
* SSID-specific probe request must be used for scans.
*/
public boolean getHiddenSSID() {
return mHiddenSSID;
}
/** {@hide} */
public void setHiddenSSID(boolean hiddenSSID) {
mHiddenSSID = hiddenSSID;
}
/**
* Map a supplicant state into a fine-grained network connectivity state.
* @param suppState the supplicant state
* @return the corresponding {@link DetailedState}
*/
public static DetailedState getDetailedStateOf(SupplicantState suppState) {
return stateMap.get(suppState);
}
/**
* Set the <code>SupplicantState</code> from the string name
* of the state.
* @param stateName the name of the state, as a <code>String</code> returned
* in an event sent by {@code wpa_supplicant}.
*/
void setSupplicantState(String stateName) {
mSupplicantState = valueOf(stateName);
}
static SupplicantState valueOf(String stateName) {
if ("4WAY_HANDSHAKE".equalsIgnoreCase(stateName))
return SupplicantState.FOUR_WAY_HANDSHAKE;
else {
try {
return SupplicantState.valueOf(stateName.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
return SupplicantState.INVALID;
}
}
}
/** {@hide} */
public static String removeDoubleQuotes(String string) {
if (string == null) return null;
final int length = string.length();
if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
return string.substring(1, length - 1);
}
return string;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
String none = "<none>";
sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid).
append(", BSSID: ").append(mBSSID == null ? none : mBSSID).
append(", MAC: ").append(mMacAddress == null ? none : mMacAddress).
append(", Supplicant state: ").
append(mSupplicantState == null ? none : mSupplicantState).
append(", RSSI: ").append(mRssi).
append(", Link speed: ").append(mLinkSpeed).
append(", Net ID: ").append(mNetworkId).
append(", Metered hint: ").append(mMeteredHint);
return sb.toString();
}
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
return 0;
}
/** Implement the Parcelable interface {@hide} */
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mNetworkId);
dest.writeInt(mRssi);
dest.writeInt(mLinkSpeed);
if (mIpAddress != null) {
dest.writeByte((byte)1);
dest.writeByteArray(mIpAddress.getAddress());
} else {
dest.writeByte((byte)0);
}
if (mWifiSsid != null) {
dest.writeInt(1);
mWifiSsid.writeToParcel(dest, flags);
} else {
dest.writeInt(0);
}
dest.writeString(mBSSID);
dest.writeString(mMacAddress);
dest.writeInt(mMeteredHint ? 1 : 0);
mSupplicantState.writeToParcel(dest, flags);
}
/** Implement the Parcelable interface {@hide} */
public static final Creator<WifiInfo> CREATOR =
new Creator<WifiInfo>() {
public WifiInfo createFromParcel(Parcel in) {
WifiInfo info = new WifiInfo();
info.setNetworkId(in.readInt());
info.setRssi(in.readInt());
info.setLinkSpeed(in.readInt());
if (in.readByte() == 1) {
try {
info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
} catch (UnknownHostException e) {}
}
if (in.readInt() == 1) {
info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
}
info.mBSSID = in.readString();
info.mMacAddress = in.readString();
info.mMeteredHint = in.readInt() != 0;
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
return info;
}
public WifiInfo[] newArray(int size) {
return new WifiInfo[size];
}
};
}