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; 18 19 import android.os.Parcelable; 20 import android.os.Parcel; 21 22 import com.android.internal.annotations.VisibleForTesting; 23 24 import java.util.EnumMap; 25 26 /** 27 * Describes the status of a network interface. 28 * <p>Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents 29 * the current network connection. 30 */ 31 public class NetworkInfo implements Parcelable { 32 33 /** 34 * Coarse-grained network state. This is probably what most applications should 35 * use, rather than {@link android.net.NetworkInfo.DetailedState DetailedState}. 36 * The mapping between the two is as follows: 37 * <br/><br/> 38 * <table> 39 * <tr><td><b>Detailed state</b></td><td><b>Coarse-grained state</b></td></tr> 40 * <tr><td><code>IDLE</code></td><td><code>DISCONNECTED</code></td></tr> 41 * <tr><td><code>SCANNING</code></td><td><code>CONNECTING</code></td></tr> 42 * <tr><td><code>CONNECTING</code></td><td><code>CONNECTING</code></td></tr> 43 * <tr><td><code>AUTHENTICATING</code></td><td><code>CONNECTING</code></td></tr> 44 * <tr><td><code>CONNECTED</code></td><td><code>CONNECTED</code></td></tr> 45 * <tr><td><code>DISCONNECTING</code></td><td><code>DISCONNECTING</code></td></tr> 46 * <tr><td><code>DISCONNECTED</code></td><td><code>DISCONNECTED</code></td></tr> 47 * <tr><td><code>UNAVAILABLE</code></td><td><code>DISCONNECTED</code></td></tr> 48 * <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr> 49 * </table> 50 */ 51 public enum State { 52 CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN 53 } 54 55 /** 56 * The fine-grained state of a network connection. This level of detail 57 * is probably of interest to few applications. Most should use 58 * {@link android.net.NetworkInfo.State State} instead. 59 */ 60 public enum DetailedState { 61 /** Ready to start data connection setup. */ 62 IDLE, 63 /** Searching for an available access point. */ 64 SCANNING, 65 /** Currently setting up data connection. */ 66 CONNECTING, 67 /** Network link established, performing authentication. */ 68 AUTHENTICATING, 69 /** Awaiting response from DHCP server in order to assign IP address information. */ 70 OBTAINING_IPADDR, 71 /** IP traffic should be available. */ 72 CONNECTED, 73 /** IP traffic is suspended */ 74 SUSPENDED, 75 /** Currently tearing down data connection. */ 76 DISCONNECTING, 77 /** IP traffic not available. */ 78 DISCONNECTED, 79 /** Attempt to connect failed. */ 80 FAILED, 81 /** Access to this network is blocked. */ 82 BLOCKED, 83 /** Link has poor connectivity. */ 84 VERIFYING_POOR_LINK, 85 /** Checking if network is a captive portal */ 86 CAPTIVE_PORTAL_CHECK 87 } 88 89 /** 90 * This is the map described in the Javadoc comment above. The positions 91 * of the elements of the array must correspond to the ordinal values 92 * of <code>DetailedState</code>. 93 */ 94 private static final EnumMap<DetailedState, State> stateMap = 95 new EnumMap<DetailedState, State>(DetailedState.class); 96 97 static { stateMap.put(DetailedState.IDLE, State.DISCONNECTED)98 stateMap.put(DetailedState.IDLE, State.DISCONNECTED); stateMap.put(DetailedState.SCANNING, State.DISCONNECTED)99 stateMap.put(DetailedState.SCANNING, State.DISCONNECTED); stateMap.put(DetailedState.CONNECTING, State.CONNECTING)100 stateMap.put(DetailedState.CONNECTING, State.CONNECTING); stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING)101 stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING); stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING)102 stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING); stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING)103 stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING); stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING)104 stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING); stateMap.put(DetailedState.CONNECTED, State.CONNECTED)105 stateMap.put(DetailedState.CONNECTED, State.CONNECTED); stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED)106 stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED); stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING)107 stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING); stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED)108 stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); stateMap.put(DetailedState.FAILED, State.DISCONNECTED)109 stateMap.put(DetailedState.FAILED, State.DISCONNECTED); stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED)110 stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED); 111 } 112 113 private int mNetworkType; 114 private int mSubtype; 115 private String mTypeName; 116 private String mSubtypeName; 117 private State mState; 118 private DetailedState mDetailedState; 119 private String mReason; 120 private String mExtraInfo; 121 private boolean mIsFailover; 122 private boolean mIsRoaming; 123 124 /** 125 * Indicates whether network connectivity is possible: 126 */ 127 private boolean mIsAvailable; 128 129 /** 130 * @hide 131 */ NetworkInfo(int type, int subtype, String typeName, String subtypeName)132 public NetworkInfo(int type, int subtype, String typeName, String subtypeName) { 133 if (!ConnectivityManager.isNetworkTypeValid(type)) { 134 throw new IllegalArgumentException("Invalid network type: " + type); 135 } 136 mNetworkType = type; 137 mSubtype = subtype; 138 mTypeName = typeName; 139 mSubtypeName = subtypeName; 140 setDetailedState(DetailedState.IDLE, null, null); 141 mState = State.UNKNOWN; 142 mIsAvailable = false; // until we're told otherwise, assume unavailable 143 mIsRoaming = false; 144 } 145 146 /** {@hide} */ NetworkInfo(NetworkInfo source)147 public NetworkInfo(NetworkInfo source) { 148 if (source != null) { 149 synchronized (source) { 150 mNetworkType = source.mNetworkType; 151 mSubtype = source.mSubtype; 152 mTypeName = source.mTypeName; 153 mSubtypeName = source.mSubtypeName; 154 mState = source.mState; 155 mDetailedState = source.mDetailedState; 156 mReason = source.mReason; 157 mExtraInfo = source.mExtraInfo; 158 mIsFailover = source.mIsFailover; 159 mIsRoaming = source.mIsRoaming; 160 mIsAvailable = source.mIsAvailable; 161 } 162 } 163 } 164 165 /** 166 * Reports the type of network to which the 167 * info in this {@code NetworkInfo} pertains. 168 * @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link 169 * ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link 170 * ConnectivityManager#TYPE_ETHERNET}, {@link ConnectivityManager#TYPE_BLUETOOTH}, or other 171 * types defined by {@link ConnectivityManager} 172 */ getType()173 public int getType() { 174 synchronized (this) { 175 return mNetworkType; 176 } 177 } 178 179 /** 180 * @hide 181 */ setType(int type)182 public void setType(int type) { 183 synchronized (this) { 184 mNetworkType = type; 185 } 186 } 187 188 /** 189 * Return a network-type-specific integer describing the subtype 190 * of the network. 191 * @return the network subtype 192 */ getSubtype()193 public int getSubtype() { 194 synchronized (this) { 195 return mSubtype; 196 } 197 } 198 199 /** 200 * @hide 201 */ setSubtype(int subtype, String subtypeName)202 public void setSubtype(int subtype, String subtypeName) { 203 synchronized (this) { 204 mSubtype = subtype; 205 mSubtypeName = subtypeName; 206 } 207 } 208 209 /** 210 * Return a human-readable name describe the type of the network, 211 * for example "WIFI" or "MOBILE". 212 * @return the name of the network type 213 */ getTypeName()214 public String getTypeName() { 215 synchronized (this) { 216 return mTypeName; 217 } 218 } 219 220 /** 221 * Return a human-readable name describing the subtype of the network. 222 * @return the name of the network subtype 223 */ getSubtypeName()224 public String getSubtypeName() { 225 synchronized (this) { 226 return mSubtypeName; 227 } 228 } 229 230 /** 231 * Indicates whether network connectivity exists or is in the process 232 * of being established. This is good for applications that need to 233 * do anything related to the network other than read or write data. 234 * For the latter, call {@link #isConnected()} instead, which guarantees 235 * that the network is fully usable. 236 * @return {@code true} if network connectivity exists or is in the process 237 * of being established, {@code false} otherwise. 238 */ isConnectedOrConnecting()239 public boolean isConnectedOrConnecting() { 240 synchronized (this) { 241 return mState == State.CONNECTED || mState == State.CONNECTING; 242 } 243 } 244 245 /** 246 * Indicates whether network connectivity exists and it is possible to establish 247 * connections and pass data. 248 * <p>Always call this before attempting to perform data transactions. 249 * @return {@code true} if network connectivity exists, {@code false} otherwise. 250 */ isConnected()251 public boolean isConnected() { 252 synchronized (this) { 253 return mState == State.CONNECTED; 254 } 255 } 256 257 /** 258 * Indicates whether network connectivity is possible. A network is unavailable 259 * when a persistent or semi-persistent condition prevents the possibility 260 * of connecting to that network. Examples include 261 * <ul> 262 * <li>The device is out of the coverage area for any network of this type.</li> 263 * <li>The device is on a network other than the home network (i.e., roaming), and 264 * data roaming has been disabled.</li> 265 * <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li> 266 * </ul> 267 * @return {@code true} if the network is available, {@code false} otherwise 268 */ isAvailable()269 public boolean isAvailable() { 270 synchronized (this) { 271 return mIsAvailable; 272 } 273 } 274 275 /** 276 * Sets if the network is available, ie, if the connectivity is possible. 277 * @param isAvailable the new availability value. 278 * 279 * @hide 280 */ setIsAvailable(boolean isAvailable)281 public void setIsAvailable(boolean isAvailable) { 282 synchronized (this) { 283 mIsAvailable = isAvailable; 284 } 285 } 286 287 /** 288 * Indicates whether the current attempt to connect to the network 289 * resulted from the ConnectivityManager trying to fail over to this 290 * network following a disconnect from another network. 291 * @return {@code true} if this is a failover attempt, {@code false} 292 * otherwise. 293 */ isFailover()294 public boolean isFailover() { 295 synchronized (this) { 296 return mIsFailover; 297 } 298 } 299 300 /** 301 * Set the failover boolean. 302 * @param isFailover {@code true} to mark the current connection attempt 303 * as a failover. 304 * @hide 305 */ setFailover(boolean isFailover)306 public void setFailover(boolean isFailover) { 307 synchronized (this) { 308 mIsFailover = isFailover; 309 } 310 } 311 312 /** 313 * Indicates whether the device is currently roaming on this network. 314 * When {@code true}, it suggests that use of data on this network 315 * may incur extra costs. 316 * @return {@code true} if roaming is in effect, {@code false} otherwise. 317 */ isRoaming()318 public boolean isRoaming() { 319 synchronized (this) { 320 return mIsRoaming; 321 } 322 } 323 324 /** {@hide} */ 325 @VisibleForTesting setRoaming(boolean isRoaming)326 public void setRoaming(boolean isRoaming) { 327 synchronized (this) { 328 mIsRoaming = isRoaming; 329 } 330 } 331 332 /** 333 * Reports the current coarse-grained state of the network. 334 * @return the coarse-grained state 335 */ getState()336 public State getState() { 337 synchronized (this) { 338 return mState; 339 } 340 } 341 342 /** 343 * Reports the current fine-grained state of the network. 344 * @return the fine-grained state 345 */ getDetailedState()346 public DetailedState getDetailedState() { 347 synchronized (this) { 348 return mDetailedState; 349 } 350 } 351 352 /** 353 * Sets the fine-grained state of the network. 354 * @param detailedState the {@link DetailedState}. 355 * @param reason a {@code String} indicating the reason for the state change, 356 * if one was supplied. May be {@code null}. 357 * @param extraInfo an optional {@code String} providing addditional network state 358 * information passed up from the lower networking layers. 359 * @hide 360 */ setDetailedState(DetailedState detailedState, String reason, String extraInfo)361 public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) { 362 synchronized (this) { 363 this.mDetailedState = detailedState; 364 this.mState = stateMap.get(detailedState); 365 this.mReason = reason; 366 this.mExtraInfo = extraInfo; 367 } 368 } 369 370 /** 371 * Set the extraInfo field. 372 * @param extraInfo an optional {@code String} providing addditional network state 373 * information passed up from the lower networking layers. 374 * @hide 375 */ setExtraInfo(String extraInfo)376 public void setExtraInfo(String extraInfo) { 377 synchronized (this) { 378 this.mExtraInfo = extraInfo; 379 } 380 } 381 382 /** 383 * Report the reason an attempt to establish connectivity failed, 384 * if one is available. 385 * @return the reason for failure, or null if not available 386 */ getReason()387 public String getReason() { 388 synchronized (this) { 389 return mReason; 390 } 391 } 392 393 /** 394 * Report the extra information about the network state, if any was 395 * provided by the lower networking layers. 396 * @return the extra information, or null if not available 397 */ getExtraInfo()398 public String getExtraInfo() { 399 synchronized (this) { 400 return mExtraInfo; 401 } 402 } 403 404 @Override toString()405 public String toString() { 406 synchronized (this) { 407 StringBuilder builder = new StringBuilder("["); 408 builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). 409 append("], state: ").append(mState).append("/").append(mDetailedState). 410 append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). 411 append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). 412 append(", roaming: ").append(mIsRoaming). 413 append(", failover: ").append(mIsFailover). 414 append(", isAvailable: ").append(mIsAvailable). 415 append("]"); 416 return builder.toString(); 417 } 418 } 419 420 /** 421 * Implement the Parcelable interface 422 * @hide 423 */ describeContents()424 public int describeContents() { 425 return 0; 426 } 427 428 /** 429 * Implement the Parcelable interface. 430 * @hide 431 */ writeToParcel(Parcel dest, int flags)432 public void writeToParcel(Parcel dest, int flags) { 433 synchronized (this) { 434 dest.writeInt(mNetworkType); 435 dest.writeInt(mSubtype); 436 dest.writeString(mTypeName); 437 dest.writeString(mSubtypeName); 438 dest.writeString(mState.name()); 439 dest.writeString(mDetailedState.name()); 440 dest.writeInt(mIsFailover ? 1 : 0); 441 dest.writeInt(mIsAvailable ? 1 : 0); 442 dest.writeInt(mIsRoaming ? 1 : 0); 443 dest.writeString(mReason); 444 dest.writeString(mExtraInfo); 445 } 446 } 447 448 /** 449 * Implement the Parcelable interface. 450 * @hide 451 */ 452 public static final Creator<NetworkInfo> CREATOR = 453 new Creator<NetworkInfo>() { 454 public NetworkInfo createFromParcel(Parcel in) { 455 int netType = in.readInt(); 456 int subtype = in.readInt(); 457 String typeName = in.readString(); 458 String subtypeName = in.readString(); 459 NetworkInfo netInfo = new NetworkInfo(netType, subtype, typeName, subtypeName); 460 netInfo.mState = State.valueOf(in.readString()); 461 netInfo.mDetailedState = DetailedState.valueOf(in.readString()); 462 netInfo.mIsFailover = in.readInt() != 0; 463 netInfo.mIsAvailable = in.readInt() != 0; 464 netInfo.mIsRoaming = in.readInt() != 0; 465 netInfo.mReason = in.readString(); 466 netInfo.mExtraInfo = in.readString(); 467 return netInfo; 468 } 469 470 public NetworkInfo[] newArray(int size) { 471 return new NetworkInfo[size]; 472 } 473 }; 474 } 475