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