WifiInfo.java revision 4eeecb25509f91ac7a6e2cde76dac782fbec5360
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 17package android.net.wifi; 18 19import android.os.Parcelable; 20import android.os.Parcel; 21import android.net.NetworkInfo.DetailedState; 22import android.net.NetworkUtils; 23import android.text.TextUtils; 24 25import java.net.InetAddress; 26import java.net.Inet4Address; 27import java.net.UnknownHostException; 28import java.util.EnumMap; 29import 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 */ 35public 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 66 /** @hide **/ 67 public static final int INVALID_RSSI = -127; 68 69 /** @hide **/ 70 public static final int MIN_RSSI = -126; 71 72 /** @hide **/ 73 public static final int MAX_RSSI = 200; 74 75 76 /** 77 * Received Signal Strength Indicator 78 */ 79 private int mRssi; 80 81 /** 82 * Link speed in Mbps 83 */ 84 public static final String LINK_SPEED_UNITS = "Mbps"; 85 private int mLinkSpeed; 86 87 /** 88 * Frequency in MHz 89 */ 90 public static final String FREQUENCY_UNITS = "MHz"; 91 private int mFrequency; 92 93 private InetAddress mIpAddress; 94 private String mMacAddress; 95 96 /** 97 * @hide 98 */ 99 public long txBad; 100 /** 101 * @hide 102 */ 103 public long txRetries; 104 /** 105 * @hide 106 */ 107 public long txSuccess; 108 /** 109 * @hide 110 */ 111 public long rxSuccess; 112 /** 113 * @hide 114 */ 115 public double txBadRate; 116 /** 117 * @hide 118 */ 119 public double txRetriesRate; 120 /** 121 * @hide 122 */ 123 public double txSuccessRate; 124 /** 125 * @hide 126 */ 127 public double rxSuccessRate; 128 129 /** 130 * @hide 131 */ 132 public int badRssiCount; 133 134 /** 135 * @hide 136 */ 137 public int linkStuckCount; 138 139 /** 140 * @hide 141 */ 142 public int lowRssiCount; 143 144 /** 145 * @hide 146 */ 147 public int score; 148 149 /** 150 * TODO: get actual timestamp and calculate true rates 151 * @hide 152 */ 153 public void updatePacketRates(WifiLinkLayerStats stats) { 154 if (stats != null) { 155 long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo; 156 long txretries = stats.retries_be + stats.retries_bk 157 + stats.retries_vi + stats.retries_vo; 158 long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo; 159 long txbad = stats.lostmpdu_be + stats.lostmpdu_bk 160 + stats.lostmpdu_vi + stats.lostmpdu_vo; 161 162 txBadRate = (txBadRate * 0.5) 163 + ((double) (txbad - txBad) * 0.5); 164 txSuccessRate = (txSuccessRate * 0.5) 165 + ((double) (txgood - txSuccess) * 0.5); 166 rxSuccessRate = (rxSuccessRate * 0.5) 167 + ((double) (rxgood - rxSuccess) * 0.5); 168 txRetriesRate = (txRetriesRate * 0.5) 169 + ((double) (txretries - txRetries) * 0.5); 170 171 txBad = txbad; 172 txSuccess = txgood; 173 rxSuccess = rxgood; 174 txRetries = txretries; 175 } else { 176 txBad = 0; 177 txSuccess = 0; 178 rxSuccess = 0; 179 txRetries = 0; 180 txBadRate = 0; 181 txSuccessRate = 0; 182 rxSuccessRate = 0; 183 txRetriesRate = 0; 184 } 185 } 186 187 188 /** 189 * This function is less powerful and used if the WifiLinkLayerStats API is not implemented 190 * at the Wifi HAL 191 * @hide 192 */ 193 public void updatePacketRates(long txPackets, long rxPackets) { 194 //paranoia 195 txBad = 0; 196 txRetries = 0; 197 txBadRate = 0; 198 txRetriesRate = 0; 199 200 txSuccessRate = (txSuccessRate * 0.5) 201 + ((double) (txPackets - txSuccess) * 0.5); 202 rxSuccessRate = (rxSuccessRate * 0.5) 203 + ((double) (rxPackets - rxSuccess) * 0.5); 204 txSuccess = txPackets; 205 rxSuccess = rxPackets; 206 } 207 208 /** 209 * Flag indicating that AP has hinted that upstream connection is metered, 210 * and sensitive to heavy data transfers. 211 */ 212 private boolean mMeteredHint; 213 214 /** @hide */ 215 public WifiInfo() { 216 mWifiSsid = null; 217 mBSSID = null; 218 mNetworkId = -1; 219 mSupplicantState = SupplicantState.UNINITIALIZED; 220 mRssi = INVALID_RSSI; 221 mLinkSpeed = -1; 222 mFrequency = -1; 223 } 224 225 /** @hide */ 226 public void reset() { 227 setInetAddress(null); 228 setBSSID(null); 229 setSSID(null); 230 setNetworkId(-1); 231 setRssi(INVALID_RSSI); 232 setLinkSpeed(-1); 233 setFrequency(-1); 234 setMeteredHint(false); 235 txBad = 0; 236 txSuccess = 0; 237 rxSuccess = 0; 238 txRetries = 0; 239 txBadRate = 0; 240 txSuccessRate = 0; 241 rxSuccessRate = 0; 242 txRetriesRate = 0; 243 lowRssiCount = 0; 244 badRssiCount = 0; 245 linkStuckCount = 0; 246 score = 0; 247 } 248 249 /** 250 * Copy constructor 251 * @hide 252 */ 253 public WifiInfo(WifiInfo source) { 254 if (source != null) { 255 mSupplicantState = source.mSupplicantState; 256 mBSSID = source.mBSSID; 257 mWifiSsid = source.mWifiSsid; 258 mNetworkId = source.mNetworkId; 259 mRssi = source.mRssi; 260 mLinkSpeed = source.mLinkSpeed; 261 mFrequency = source.mFrequency; 262 mIpAddress = source.mIpAddress; 263 mMacAddress = source.mMacAddress; 264 mMeteredHint = source.mMeteredHint; 265 txBad = source.txBad; 266 txRetries = source.txRetries; 267 txSuccess = source.txSuccess; 268 rxSuccess = source.rxSuccess; 269 txBadRate = source.txBadRate; 270 txRetriesRate = source.txRetriesRate; 271 txSuccessRate = source.txSuccessRate; 272 rxSuccessRate = source.rxSuccessRate; 273 score = source.score; 274 badRssiCount = source.badRssiCount; 275 lowRssiCount = source.lowRssiCount; 276 linkStuckCount = source.linkStuckCount; 277 } 278 } 279 280 /** @hide */ 281 public void setSSID(WifiSsid wifiSsid) { 282 mWifiSsid = wifiSsid; 283 } 284 285 /** 286 * Returns the service set identifier (SSID) of the current 802.11 network. 287 * If the SSID can be decoded as UTF-8, it will be returned surrounded by double 288 * quotation marks. Otherwise, it is returned as a string of hex digits. The 289 * SSID may be {@code null} if there is no network currently connected. 290 * @return the SSID 291 */ 292 public String getSSID() { 293 if (mWifiSsid != null) { 294 String unicode = mWifiSsid.toString(); 295 if (!TextUtils.isEmpty(unicode)) { 296 return "\"" + unicode + "\""; 297 } else { 298 return mWifiSsid.getHexString(); 299 } 300 } 301 return WifiSsid.NONE; 302 } 303 304 /** @hide */ 305 public WifiSsid getWifiSsid() { 306 return mWifiSsid; 307 } 308 309 /** @hide */ 310 public void setBSSID(String BSSID) { 311 mBSSID = BSSID; 312 } 313 314 /** 315 * Return the basic service set identifier (BSSID) of the current access point. 316 * The BSSID may be {@code null} if there is no network currently connected. 317 * @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX} 318 */ 319 public String getBSSID() { 320 return mBSSID; 321 } 322 323 /** 324 * Returns the received signal strength indicator of the current 802.11 325 * network, in dBm. 326 * @return the RSSI, in the range -127 to 200 327 */ 328 public int getRssi() { 329 return mRssi; 330 } 331 332 /** @hide */ 333 public void setRssi(int rssi) { 334 if (rssi < INVALID_RSSI) 335 rssi = INVALID_RSSI; 336 if (rssi > MAX_RSSI) 337 rssi = MAX_RSSI; 338 mRssi = rssi; 339 } 340 341 /** 342 * Returns the current link speed in {@link #LINK_SPEED_UNITS}. 343 * @return the link speed. 344 * @see #LINK_SPEED_UNITS 345 */ 346 public int getLinkSpeed() { 347 return mLinkSpeed; 348 } 349 350 /** @hide */ 351 public void setLinkSpeed(int linkSpeed) { 352 this.mLinkSpeed = linkSpeed; 353 } 354 355 /** 356 * Returns the current frequency in {@link #FREQUENCY_UNITS}. 357 * @return the frequency. 358 * @see #FREQUENCY_UNITS 359 */ 360 public int getFrequency() { 361 return mFrequency; 362 } 363 364 /** @hide */ 365 public void setFrequency(int frequency) { 366 this.mFrequency = frequency; 367 } 368 369 /** 370 * @hide 371 * TODO: makes real freq boundaries 372 */ 373 public boolean is24GHz() { 374 return ScanResult.is24GHz(mFrequency); 375 } 376 377 /** 378 * @hide 379 * TODO: makes real freq boundaries 380 */ 381 public boolean is5GHz() { 382 return ScanResult.is5GHz(mFrequency); 383 } 384 385 /** 386 * Record the MAC address of the WLAN interface 387 * @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form 388 * @hide 389 */ 390 public void setMacAddress(String macAddress) { 391 this.mMacAddress = macAddress; 392 } 393 394 public String getMacAddress() { 395 return mMacAddress; 396 } 397 398 /** {@hide} */ 399 public void setMeteredHint(boolean meteredHint) { 400 mMeteredHint = meteredHint; 401 } 402 403 /** {@hide} */ 404 public boolean getMeteredHint() { 405 return mMeteredHint; 406 } 407 408 /** @hide */ 409 public void setNetworkId(int id) { 410 mNetworkId = id; 411 } 412 413 /** 414 * Each configured network has a unique small integer ID, used to identify 415 * the network when performing operations on the supplicant. This method 416 * returns the ID for the currently connected network. 417 * @return the network ID, or -1 if there is no currently connected network 418 */ 419 public int getNetworkId() { 420 return mNetworkId; 421 } 422 423 /** 424 * Return the detailed state of the supplicant's negotiation with an 425 * access point, in the form of a {@link SupplicantState SupplicantState} object. 426 * @return the current {@link SupplicantState SupplicantState} 427 */ 428 public SupplicantState getSupplicantState() { 429 return mSupplicantState; 430 } 431 432 /** @hide */ 433 public void setSupplicantState(SupplicantState state) { 434 mSupplicantState = state; 435 } 436 437 /** @hide */ 438 public void setInetAddress(InetAddress address) { 439 mIpAddress = address; 440 } 441 442 public int getIpAddress() { 443 int result = 0; 444 if (mIpAddress instanceof Inet4Address) { 445 result = NetworkUtils.inetAddressToInt((Inet4Address)mIpAddress); 446 } 447 return result; 448 } 449 450 /** 451 * @return {@code true} if this network does not broadcast its SSID, so an 452 * SSID-specific probe request must be used for scans. 453 */ 454 public boolean getHiddenSSID() { 455 return mWifiSsid.isHidden(); 456 } 457 458 /** 459 * Map a supplicant state into a fine-grained network connectivity state. 460 * @param suppState the supplicant state 461 * @return the corresponding {@link DetailedState} 462 */ 463 public static DetailedState getDetailedStateOf(SupplicantState suppState) { 464 return stateMap.get(suppState); 465 } 466 467 /** 468 * Set the <code>SupplicantState</code> from the string name 469 * of the state. 470 * @param stateName the name of the state, as a <code>String</code> returned 471 * in an event sent by {@code wpa_supplicant}. 472 */ 473 void setSupplicantState(String stateName) { 474 mSupplicantState = valueOf(stateName); 475 } 476 477 static SupplicantState valueOf(String stateName) { 478 if ("4WAY_HANDSHAKE".equalsIgnoreCase(stateName)) 479 return SupplicantState.FOUR_WAY_HANDSHAKE; 480 else { 481 try { 482 return SupplicantState.valueOf(stateName.toUpperCase(Locale.ROOT)); 483 } catch (IllegalArgumentException e) { 484 return SupplicantState.INVALID; 485 } 486 } 487 } 488 489 /** {@hide} */ 490 public static String removeDoubleQuotes(String string) { 491 if (string == null) return null; 492 final int length = string.length(); 493 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) { 494 return string.substring(1, length - 1); 495 } 496 return string; 497 } 498 499 @Override 500 public String toString() { 501 StringBuffer sb = new StringBuffer(); 502 String none = "<none>"; 503 504 sb.append("SSID: ").append(mWifiSsid == null ? WifiSsid.NONE : mWifiSsid). 505 append(", BSSID: ").append(mBSSID == null ? none : mBSSID). 506 append(", MAC: ").append(mMacAddress == null ? none : mMacAddress). 507 append(", Supplicant state: "). 508 append(mSupplicantState == null ? none : mSupplicantState). 509 append(", RSSI: ").append(mRssi). 510 append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS). 511 append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS). 512 append(", Net ID: ").append(mNetworkId). 513 append(", Metered hint: ").append(mMeteredHint). 514 append(", score: ").append(Integer.toString(score)); 515 return sb.toString(); 516 } 517 518 /** Implement the Parcelable interface {@hide} */ 519 public int describeContents() { 520 return 0; 521 } 522 523 /** Implement the Parcelable interface {@hide} */ 524 public void writeToParcel(Parcel dest, int flags) { 525 dest.writeInt(mNetworkId); 526 dest.writeInt(mRssi); 527 dest.writeInt(mLinkSpeed); 528 dest.writeInt(mFrequency); 529 if (mIpAddress != null) { 530 dest.writeByte((byte)1); 531 dest.writeByteArray(mIpAddress.getAddress()); 532 } else { 533 dest.writeByte((byte)0); 534 } 535 if (mWifiSsid != null) { 536 dest.writeInt(1); 537 mWifiSsid.writeToParcel(dest, flags); 538 } else { 539 dest.writeInt(0); 540 } 541 dest.writeString(mBSSID); 542 dest.writeString(mMacAddress); 543 dest.writeInt(mMeteredHint ? 1 : 0); 544 dest.writeInt(score); 545 dest.writeDouble(txSuccessRate); 546 dest.writeDouble(txRetriesRate); 547 dest.writeDouble(txBadRate); 548 dest.writeDouble(rxSuccessRate); 549 dest.writeInt(badRssiCount); 550 dest.writeInt(lowRssiCount); 551 mSupplicantState.writeToParcel(dest, flags); 552 } 553 554 /** Implement the Parcelable interface {@hide} */ 555 public static final Creator<WifiInfo> CREATOR = 556 new Creator<WifiInfo>() { 557 public WifiInfo createFromParcel(Parcel in) { 558 WifiInfo info = new WifiInfo(); 559 info.setNetworkId(in.readInt()); 560 info.setRssi(in.readInt()); 561 info.setLinkSpeed(in.readInt()); 562 info.setFrequency(in.readInt()); 563 if (in.readByte() == 1) { 564 try { 565 info.setInetAddress(InetAddress.getByAddress(in.createByteArray())); 566 } catch (UnknownHostException e) {} 567 } 568 if (in.readInt() == 1) { 569 info.mWifiSsid = WifiSsid.CREATOR.createFromParcel(in); 570 } 571 info.mBSSID = in.readString(); 572 info.mMacAddress = in.readString(); 573 info.mMeteredHint = in.readInt() != 0; 574 info.score = in.readInt(); 575 info.txSuccessRate = in.readDouble(); 576 info.txRetriesRate = in.readDouble(); 577 info.txBadRate = in.readDouble(); 578 info.rxSuccessRate = in.readDouble(); 579 info.badRssiCount = in.readInt(); 580 info.lowRssiCount = in.readInt(); 581 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in); 582 return info; 583 } 584 585 public WifiInfo[] newArray(int size) { 586 return new WifiInfo[size]; 587 } 588 }; 589} 590