Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net.wifi;
     18 
     19 import android.os.Parcelable;
     20 import android.os.Parcel;
     21 import android.net.NetworkInfo.DetailedState;
     22 import android.net.NetworkUtils;
     23 import android.text.TextUtils;
     24 
     25 import java.net.InetAddress;
     26 import java.net.Inet4Address;
     27 import java.net.UnknownHostException;
     28 import java.util.EnumMap;
     29 import java.util.Locale;
     30 
     31 /**
     32  * Describes the state of any Wifi connection that is active or
     33  * is in the process of being set up.
     34  */
     35 public class WifiInfo implements Parcelable {
     36     private static final String TAG = "WifiInfo";
     37     /**
     38      * This is the map described in the Javadoc comment above. The positions
     39      * of the elements of the array must correspond to the ordinal values
     40      * of <code>DetailedState</code>.
     41      */
     42     private static final EnumMap<SupplicantState, DetailedState> stateMap =
     43         new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);
     44 
     45     static {
     46         stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
     47         stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
     48         stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
     49         stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
     50         stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
     51         stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
     52         stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
     53         stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);
     54         stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING);
     55         stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR);
     56         stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED);
     57         stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE);
     58         stateMap.put(SupplicantState.INVALID, DetailedState.FAILED);
     59     }
     60 
     61     private SupplicantState mSupplicantState;
     62     private String mBSSID;
     63     private WifiSsid mWifiSsid;
     64     private int mNetworkId;
     65     private boolean mHiddenSSID;
     66     /** Received Signal Strength Indicator */
     67     private int mRssi;
     68 
     69     /** Link speed in Mbps */
     70     public static final String LINK_SPEED_UNITS = "Mbps";
     71     private int mLinkSpeed;
     72 
     73     private InetAddress mIpAddress;
     74     private String mMacAddress;
     75 
     76     /**
     77      * Flag indicating that AP has hinted that upstream connection is metered,
     78      * and sensitive to heavy data transfers.
     79      */
     80     private boolean mMeteredHint;
     81 
     82     WifiInfo() {
     83         mWifiSsid = null;
     84         mBSSID = null;
     85         mNetworkId = -1;
     86         mSupplicantState = SupplicantState.UNINITIALIZED;
     87         mRssi = -9999;
     88         mLinkSpeed = -1;
     89         mHiddenSSID = false;
     90     }
     91 
     92     /**
     93      * Copy constructor
     94      * @hide
     95      */
     96     public WifiInfo(WifiInfo source) {
     97         if (source != null) {
     98             mSupplicantState = source.mSupplicantState;
     99             mBSSID = source.mBSSID;
    100             mWifiSsid = source.mWifiSsid;
    101             mNetworkId = source.mNetworkId;
    102             mHiddenSSID = source.mHiddenSSID;
    103             mRssi = source.mRssi;
    104             mLinkSpeed = source.mLinkSpeed;
    105             mIpAddress = source.mIpAddress;
    106             mMacAddress = source.mMacAddress;
    107             mMeteredHint = source.mMeteredHint;
    108         }
    109     }
    110 
    111     void setSSID(WifiSsid wifiSsid) {
    112         mWifiSsid = wifiSsid;
    113         // network is considered not hidden by default
    114         mHiddenSSID = false;
    115     }
    116 
    117     /**
    118      * Returns the service set identifier (SSID) of the current 802.11 network.
    119      * If the SSID can be decoded as UTF-8, it will be returned surrounded by double
    120      * quotation marks. Otherwise, it is returned as a string of hex digits. The
    121      * SSID may be {@code null} if there is no network currently connected.
    122      * @return the SSID
    123      */
    124     public String getSSID() {
    125         if (mWifiSsid != null) {
    126             String unicode = mWifiSsid.toString();
    127             if (!TextUtils.isEmpty(unicode)) {
    128                 return "\"" + unicode + "\"";
    129             } else {
    130                 return mWifiSsid.getHexString();
    131             }
    132         }
    133         return WifiSsid.NONE;
    134     }
    135 
    136     /** @hide */
    137     public WifiSsid getWifiSsid() {
    138         return mWifiSsid;
    139     }
    140 
    141     void setBSSID(String BSSID) {
    142         mBSSID = BSSID;
    143     }
    144 
    145     /**
    146      * Return the basic service set identifier (BSSID) of the current access point.
    147      * The BSSID may be {@code null} if there is no network currently connected.
    148      * @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
    149      */
    150     public String getBSSID() {
    151         return mBSSID;
    152     }
    153 
    154     /**
    155      * Returns the received signal strength indicator of the current 802.11
    156      * network.
    157      * <p><strong>This is not normalized, but should be!</strong></p>
    158      * @return the RSSI, in the range ??? to ???
    159      */
    160     public int getRssi() {
    161         return mRssi;
    162     }
    163 
    164     void setRssi(int rssi) {
    165         mRssi = rssi;
    166     }
    167 
    168     /**
    169      * Returns the current link speed in {@link #LINK_SPEED_UNITS}.
    170      * @return the link speed.
    171      * @see #LINK_SPEED_UNITS
    172      */
    173     public int getLinkSpeed() {
    174         return mLinkSpeed;
    175     }
    176 
    177     void setLinkSpeed(int linkSpeed) {
    178         this.mLinkSpeed = linkSpeed;
    179     }
    180 
    181     /**
    182      * Record the MAC address of the WLAN interface
    183      * @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
    184      */
    185     void setMacAddress(String macAddress) {
    186         this.mMacAddress = macAddress;
    187     }
    188 
    189     public String getMacAddress() {
    190         return mMacAddress;
    191     }
    192 
    193     /** {@hide} */
    194     public void setMeteredHint(boolean meteredHint) {
    195         mMeteredHint = meteredHint;
    196     }
    197 
    198     /** {@hide} */
    199     public boolean getMeteredHint() {
    200         return mMeteredHint;
    201     }
    202 
    203     void setNetworkId(int id) {
    204         mNetworkId = id;
    205     }
    206 
    207     /**
    208      * Each configured network has a unique small integer ID, used to identify
    209      * the network when performing operations on the supplicant. This method
    210      * returns the ID for the currently connected network.
    211      * @return the network ID, or -1 if there is no currently connected network
    212      */
    213     public int getNetworkId() {
    214         return mNetworkId;
    215     }
    216 
    217     /**
    218      * Return the detailed state of the supplicant's negotiation with an
    219      * access point, in the form of a {@link SupplicantState SupplicantState} object.
    220      * @return the current {@link SupplicantState SupplicantState}
    221      */
    222     public SupplicantState getSupplicantState() {
    223         return mSupplicantState;
    224     }
    225 
    226     void setSupplicantState(SupplicantState state) {
    227         mSupplicantState = state;
    228     }
    229 
    230     void setInetAddress(InetAddress address) {
    231         mIpAddress = address;
    232     }
    233 
    234     public int getIpAddress() {
    235         int result = 0;
    236         if (mIpAddress instanceof Inet4Address) {
    237             result = NetworkUtils.inetAddressToInt((Inet4Address)mIpAddress);
    238         }
    239         return result;
    240     }
    241 
    242     /**
    243      * @return {@code true} if this network does not broadcast its SSID, so an
    244      * SSID-specific probe request must be used for scans.
    245      */
    246     public boolean getHiddenSSID() {
    247         return mHiddenSSID;
    248     }
    249 
    250     /** {@hide} */
    251     public void setHiddenSSID(boolean hiddenSSID) {
    252         mHiddenSSID = hiddenSSID;
    253     }
    254 
    255    /**
    256      * Map a supplicant state into a fine-grained network connectivity state.
    257      * @param suppState the supplicant state
    258      * @return the corresponding {@link DetailedState}
    259      */
    260     public static DetailedState getDetailedStateOf(SupplicantState suppState) {
    261         return stateMap.get(suppState);
    262     }
    263 
    264     /**
    265      * Set the <code>SupplicantState</code> from the string name
    266      * of the state.
    267      * @param stateName the name of the state, as a <code>String</code> returned
    268      * in an event sent by {@code wpa_supplicant}.
    269      */
    270     void setSupplicantState(String stateName) {
    271         mSupplicantState = valueOf(stateName);
    272     }
    273 
    274     static SupplicantState valueOf(String stateName) {
    275         if ("4WAY_HANDSHAKE".equalsIgnoreCase(stateName))
    276             return SupplicantState.FOUR_WAY_HANDSHAKE;
    277         else {
    278             try {
    279                 return SupplicantState.valueOf(stateName.toUpperCase(Locale.ROOT));
    280             } catch (IllegalArgumentException e) {
    281                 return SupplicantState.INVALID;
    282             }
    283         }
    284     }
    285 
    286     /** {@hide} */
    287     public static String removeDoubleQuotes(String string) {
    288         if (string == null) return null;
    289         final int length = string.length();
    290         if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
    291             return string.substring(1, length - 1);
    292         }
    293         return string;
    294     }
    295 
    296     @Override
    297     public String toString() {
    298         StringBuffer sb = new StringBuffer();
    299         String none = "<none>";
    300 
    301         sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid).
    302             append(", BSSID: ").append(mBSSID == null ? none : mBSSID).
    303             append(", MAC: ").append(mMacAddress == null ? none : mMacAddress).
    304             append(", Supplicant state: ").
    305             append(mSupplicantState == null ? none : mSupplicantState).
    306             append(", RSSI: ").append(mRssi).
    307             append(", Link speed: ").append(mLinkSpeed).
    308             append(", Net ID: ").append(mNetworkId).
    309             append(", Metered hint: ").append(mMeteredHint);
    310 
    311         return sb.toString();
    312     }
    313 
    314     /** Implement the Parcelable interface {@hide} */
    315     public int describeContents() {
    316         return 0;
    317     }
    318 
    319     /** Implement the Parcelable interface {@hide} */
    320     public void writeToParcel(Parcel dest, int flags) {
    321         dest.writeInt(mNetworkId);
    322         dest.writeInt(mRssi);
    323         dest.writeInt(mLinkSpeed);
    324         if (mIpAddress != null) {
    325             dest.writeByte((byte)1);
    326             dest.writeByteArray(mIpAddress.getAddress());
    327         } else {
    328             dest.writeByte((byte)0);
    329         }
    330         if (mWifiSsid != null) {
    331             dest.writeInt(1);
    332             mWifiSsid.writeToParcel(dest, flags);
    333         } else {
    334             dest.writeInt(0);
    335         }
    336         dest.writeString(mBSSID);
    337         dest.writeString(mMacAddress);
    338         dest.writeInt(mMeteredHint ? 1 : 0);
    339         mSupplicantState.writeToParcel(dest, flags);
    340     }
    341 
    342     /** Implement the Parcelable interface {@hide} */
    343     public static final Creator<WifiInfo> CREATOR =
    344         new Creator<WifiInfo>() {
    345             public WifiInfo createFromParcel(Parcel in) {
    346                 WifiInfo info = new WifiInfo();
    347                 info.setNetworkId(in.readInt());
    348                 info.setRssi(in.readInt());
    349                 info.setLinkSpeed(in.readInt());
    350                 if (in.readByte() == 1) {
    351                     try {
    352                         info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
    353                     } catch (UnknownHostException e) {}
    354                 }
    355                 if (in.readInt() == 1) {
    356                     info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in);
    357                 }
    358                 info.mBSSID = in.readString();
    359                 info.mMacAddress = in.readString();
    360                 info.mMeteredHint = in.readInt() != 0;
    361                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
    362                 return info;
    363             }
    364 
    365             public WifiInfo[] newArray(int size) {
    366                 return new WifiInfo[size];
    367             }
    368         };
    369 }
    370