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