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 { 98 stateMap.put(DetailedState.IDLE, State.DISCONNECTED); 99 stateMap.put(DetailedState.SCANNING, State.DISCONNECTED); 100 stateMap.put(DetailedState.CONNECTING, State.CONNECTING); 101 stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING); 102 stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING); 103 stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING); 104 stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING); 105 stateMap.put(DetailedState.CONNECTED, State.CONNECTED); 106 stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED); 107 stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING); 108 stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); 109 stateMap.put(DetailedState.FAILED, 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 * Indicates whether network connectivity is possible: 125 */ 126 private boolean mIsAvailable; 127 128 /** 129 * @param type network type 130 * @deprecated 131 * @hide because this constructor was only meant for internal use (and 132 * has now been superseded by the package-private constructor below). 133 */ 134 public NetworkInfo(int type) {} 135 136 /** 137 * @hide 138 */ 139 public NetworkInfo(int type, int subtype, String typeName, String subtypeName) { 140 if (!ConnectivityManager.isNetworkTypeValid(type)) { 141 throw new IllegalArgumentException("Invalid network type: " + type); 142 } 143 mNetworkType = type; 144 mSubtype = subtype; 145 mTypeName = typeName; 146 mSubtypeName = subtypeName; 147 setDetailedState(DetailedState.IDLE, null, null); 148 mState = State.UNKNOWN; 149 mIsAvailable = false; // until we're told otherwise, assume unavailable 150 mIsRoaming = false; 151 } 152 153 /** {@hide} */ 154 public NetworkInfo(NetworkInfo source) { 155 if (source != null) { 156 mNetworkType = source.mNetworkType; 157 mSubtype = source.mSubtype; 158 mTypeName = source.mTypeName; 159 mSubtypeName = source.mSubtypeName; 160 mState = source.mState; 161 mDetailedState = source.mDetailedState; 162 mReason = source.mReason; 163 mExtraInfo = source.mExtraInfo; 164 mIsFailover = source.mIsFailover; 165 mIsRoaming = source.mIsRoaming; 166 mIsAvailable = source.mIsAvailable; 167 } 168 } 169 170 /** 171 * Reports the type of network to which the 172 * info in this {@code NetworkInfo} pertains. 173 * @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link 174 * ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link 175 * ConnectivityManager#TYPE_ETHERNET}, {@link ConnectivityManager#TYPE_BLUETOOTH}, or other 176 * types defined by {@link ConnectivityManager} 177 */ 178 public int getType() { 179 synchronized (this) { 180 return mNetworkType; 181 } 182 } 183 184 /** 185 * Return a network-type-specific integer describing the subtype 186 * of the network. 187 * @return the network subtype 188 */ 189 public int getSubtype() { 190 synchronized (this) { 191 return mSubtype; 192 } 193 } 194 195 void setSubtype(int subtype, String subtypeName) { 196 synchronized (this) { 197 mSubtype = subtype; 198 mSubtypeName = subtypeName; 199 } 200 } 201 202 /** 203 * Return a human-readable name describe the type of the network, 204 * for example "WIFI" or "MOBILE". 205 * @return the name of the network type 206 */ 207 public String getTypeName() { 208 synchronized (this) { 209 return mTypeName; 210 } 211 } 212 213 /** 214 * Return a human-readable name describing the subtype of the network. 215 * @return the name of the network subtype 216 */ 217 public String getSubtypeName() { 218 synchronized (this) { 219 return mSubtypeName; 220 } 221 } 222 223 /** 224 * Indicates whether network connectivity exists or is in the process 225 * of being established. This is good for applications that need to 226 * do anything related to the network other than read or write data. 227 * For the latter, call {@link #isConnected()} instead, which guarantees 228 * that the network is fully usable. 229 * @return {@code true} if network connectivity exists or is in the process 230 * of being established, {@code false} otherwise. 231 */ 232 public boolean isConnectedOrConnecting() { 233 synchronized (this) { 234 return mState == State.CONNECTED || mState == State.CONNECTING; 235 } 236 } 237 238 /** 239 * Indicates whether network connectivity exists and it is possible to establish 240 * connections and pass data. 241 * <p>Always call this before attempting to perform data transactions. 242 * @return {@code true} if network connectivity exists, {@code false} otherwise. 243 */ 244 public boolean isConnected() { 245 synchronized (this) { 246 return mState == State.CONNECTED; 247 } 248 } 249 250 /** 251 * Indicates whether network connectivity is possible. A network is unavailable 252 * when a persistent or semi-persistent condition prevents the possibility 253 * of connecting to that network. Examples include 254 * <ul> 255 * <li>The device is out of the coverage area for any network of this type.</li> 256 * <li>The device is on a network other than the home network (i.e., roaming), and 257 * data roaming has been disabled.</li> 258 * <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li> 259 * </ul> 260 * @return {@code true} if the network is available, {@code false} otherwise 261 */ 262 public boolean isAvailable() { 263 synchronized (this) { 264 return mIsAvailable; 265 } 266 } 267 268 /** 269 * Sets if the network is available, ie, if the connectivity is possible. 270 * @param isAvailable the new availability value. 271 * 272 * @hide 273 */ 274 public void setIsAvailable(boolean isAvailable) { 275 synchronized (this) { 276 mIsAvailable = isAvailable; 277 } 278 } 279 280 /** 281 * Indicates whether the current attempt to connect to the network 282 * resulted from the ConnectivityManager trying to fail over to this 283 * network following a disconnect from another network. 284 * @return {@code true} if this is a failover attempt, {@code false} 285 * otherwise. 286 */ 287 public boolean isFailover() { 288 synchronized (this) { 289 return mIsFailover; 290 } 291 } 292 293 /** 294 * Set the failover boolean. 295 * @param isFailover {@code true} to mark the current connection attempt 296 * as a failover. 297 * @hide 298 */ 299 public void setFailover(boolean isFailover) { 300 synchronized (this) { 301 mIsFailover = isFailover; 302 } 303 } 304 305 /** 306 * Indicates whether the device is currently roaming on this network. 307 * When {@code true}, it suggests that use of data on this network 308 * may incur extra costs. 309 * @return {@code true} if roaming is in effect, {@code false} otherwise. 310 */ 311 public boolean isRoaming() { 312 synchronized (this) { 313 return mIsRoaming; 314 } 315 } 316 317 /** {@hide} */ 318 @VisibleForTesting 319 public void setRoaming(boolean isRoaming) { 320 synchronized (this) { 321 mIsRoaming = isRoaming; 322 } 323 } 324 325 /** 326 * Reports the current coarse-grained state of the network. 327 * @return the coarse-grained state 328 */ 329 public State getState() { 330 synchronized (this) { 331 return mState; 332 } 333 } 334 335 /** 336 * Reports the current fine-grained state of the network. 337 * @return the fine-grained state 338 */ 339 public DetailedState getDetailedState() { 340 synchronized (this) { 341 return mDetailedState; 342 } 343 } 344 345 /** 346 * Sets the fine-grained state of the network. 347 * @param detailedState the {@link DetailedState}. 348 * @param reason a {@code String} indicating the reason for the state change, 349 * if one was supplied. May be {@code null}. 350 * @param extraInfo an optional {@code String} providing addditional network state 351 * information passed up from the lower networking layers. 352 * @hide 353 */ 354 public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) { 355 synchronized (this) { 356 this.mDetailedState = detailedState; 357 this.mState = stateMap.get(detailedState); 358 this.mReason = reason; 359 this.mExtraInfo = extraInfo; 360 } 361 } 362 363 /** 364 * Set the extraInfo field. 365 * @param extraInfo an optional {@code String} providing addditional network state 366 * information passed up from the lower networking layers. 367 * @hide 368 */ 369 public void setExtraInfo(String extraInfo) { 370 synchronized (this) { 371 this.mExtraInfo = extraInfo; 372 } 373 } 374 375 /** 376 * Report the reason an attempt to establish connectivity failed, 377 * if one is available. 378 * @return the reason for failure, or null if not available 379 */ 380 public String getReason() { 381 synchronized (this) { 382 return mReason; 383 } 384 } 385 386 /** 387 * Report the extra information about the network state, if any was 388 * provided by the lower networking layers., 389 * if one is available. 390 * @return the extra information, or null if not available 391 */ 392 public String getExtraInfo() { 393 synchronized (this) { 394 return mExtraInfo; 395 } 396 } 397 398 @Override 399 public String toString() { 400 synchronized (this) { 401 StringBuilder builder = new StringBuilder("NetworkInfo: "); 402 builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). 403 append("], state: ").append(mState).append("/").append(mDetailedState). 404 append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). 405 append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). 406 append(", roaming: ").append(mIsRoaming). 407 append(", failover: ").append(mIsFailover). 408 append(", isAvailable: ").append(mIsAvailable); 409 return builder.toString(); 410 } 411 } 412 413 /** 414 * Implement the Parcelable interface 415 * @hide 416 */ 417 public int describeContents() { 418 return 0; 419 } 420 421 /** 422 * Implement the Parcelable interface. 423 * @hide 424 */ 425 public void writeToParcel(Parcel dest, int flags) { 426 synchronized (this) { 427 dest.writeInt(mNetworkType); 428 dest.writeInt(mSubtype); 429 dest.writeString(mTypeName); 430 dest.writeString(mSubtypeName); 431 dest.writeString(mState.name()); 432 dest.writeString(mDetailedState.name()); 433 dest.writeInt(mIsFailover ? 1 : 0); 434 dest.writeInt(mIsAvailable ? 1 : 0); 435 dest.writeInt(mIsRoaming ? 1 : 0); 436 dest.writeString(mReason); 437 dest.writeString(mExtraInfo); 438 } 439 } 440 441 /** 442 * Implement the Parcelable interface. 443 * @hide 444 */ 445 public static final Creator<NetworkInfo> CREATOR = 446 new Creator<NetworkInfo>() { 447 public NetworkInfo createFromParcel(Parcel in) { 448 int netType = in.readInt(); 449 int subtype = in.readInt(); 450 String typeName = in.readString(); 451 String subtypeName = in.readString(); 452 NetworkInfo netInfo = new NetworkInfo(netType, subtype, typeName, subtypeName); 453 netInfo.mState = State.valueOf(in.readString()); 454 netInfo.mDetailedState = DetailedState.valueOf(in.readString()); 455 netInfo.mIsFailover = in.readInt() != 0; 456 netInfo.mIsAvailable = in.readInt() != 0; 457 netInfo.mIsRoaming = in.readInt() != 0; 458 netInfo.mReason = in.readString(); 459 netInfo.mExtraInfo = in.readString(); 460 return netInfo; 461 } 462 463 public NetworkInfo[] newArray(int size) { 464 return new NetworkInfo[size]; 465 } 466 }; 467 } 468