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