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.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.telephony.Annotation.NetworkType; 25 import android.text.TextUtils; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 29 import java.util.EnumMap; 30 31 /** 32 * Describes the status of a network interface. 33 * <p>Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents 34 * the current network connection. 35 * 36 * @deprecated Callers should instead use the {@link ConnectivityManager.NetworkCallback} API to 37 * learn about connectivity changes, or switch to use 38 * {@link ConnectivityManager#getNetworkCapabilities} or 39 * {@link ConnectivityManager#getLinkProperties} to get information synchronously. Keep 40 * in mind that while callbacks are guaranteed to be called for every event in order, 41 * synchronous calls have no such constraints, and as such it is unadvisable to use the 42 * synchronous methods inside the callbacks as they will often not offer a view of 43 * networking that is consistent (that is: they may return a past or a future state with 44 * respect to the event being processed by the callback). Instead, callers are advised 45 * to only use the arguments of the callbacks, possibly memorizing the specific bits of 46 * information they need to keep from one callback to another. 47 */ 48 @Deprecated 49 public class NetworkInfo implements Parcelable { 50 51 /** 52 * Coarse-grained network state. This is probably what most applications should 53 * use, rather than {@link android.net.NetworkInfo.DetailedState DetailedState}. 54 * The mapping between the two is as follows: 55 * <br/><br/> 56 * <table> 57 * <tr><td><b>Detailed state</b></td><td><b>Coarse-grained state</b></td></tr> 58 * <tr><td><code>IDLE</code></td><td><code>DISCONNECTED</code></td></tr> 59 * <tr><td><code>SCANNING</code></td><td><code>DISCONNECTED</code></td></tr> 60 * <tr><td><code>CONNECTING</code></td><td><code>CONNECTING</code></td></tr> 61 * <tr><td><code>AUTHENTICATING</code></td><td><code>CONNECTING</code></td></tr> 62 * <tr><td><code>OBTAINING_IPADDR</code></td><td><code>CONNECTING</code></td></tr> 63 * <tr><td><code>VERIFYING_POOR_LINK</code></td><td><code>CONNECTING</code></td></tr> 64 * <tr><td><code>CAPTIVE_PORTAL_CHECK</code></td><td><code>CONNECTING</code></td></tr> 65 * <tr><td><code>CONNECTED</code></td><td><code>CONNECTED</code></td></tr> 66 * <tr><td><code>SUSPENDED</code></td><td><code>SUSPENDED</code></td></tr> 67 * <tr><td><code>DISCONNECTING</code></td><td><code>DISCONNECTING</code></td></tr> 68 * <tr><td><code>DISCONNECTED</code></td><td><code>DISCONNECTED</code></td></tr> 69 * <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr> 70 * <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr> 71 * </table> 72 * 73 * @deprecated See {@link NetworkInfo}. 74 */ 75 @Deprecated 76 public enum State { 77 CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN 78 } 79 80 /** 81 * The fine-grained state of a network connection. This level of detail 82 * is probably of interest to few applications. Most should use 83 * {@link android.net.NetworkInfo.State State} instead. 84 * 85 * @deprecated See {@link NetworkInfo}. 86 */ 87 @Deprecated 88 public enum DetailedState { 89 /** Ready to start data connection setup. */ 90 IDLE, 91 /** Searching for an available access point. */ 92 SCANNING, 93 /** Currently setting up data connection. */ 94 CONNECTING, 95 /** Network link established, performing authentication. */ 96 AUTHENTICATING, 97 /** Awaiting response from DHCP server in order to assign IP address information. */ 98 OBTAINING_IPADDR, 99 /** IP traffic should be available. */ 100 CONNECTED, 101 /** IP traffic is suspended */ 102 SUSPENDED, 103 /** Currently tearing down data connection. */ 104 DISCONNECTING, 105 /** IP traffic not available. */ 106 DISCONNECTED, 107 /** Attempt to connect failed. */ 108 FAILED, 109 /** Access to this network is blocked. */ 110 BLOCKED, 111 /** Link has poor connectivity. */ 112 VERIFYING_POOR_LINK, 113 /** Checking if network is a captive portal */ 114 CAPTIVE_PORTAL_CHECK 115 } 116 117 /** 118 * This is the map described in the Javadoc comment above. The positions 119 * of the elements of the array must correspond to the ordinal values 120 * of <code>DetailedState</code>. 121 */ 122 private static final EnumMap<DetailedState, State> stateMap = 123 new EnumMap<DetailedState, State>(DetailedState.class); 124 125 static { stateMap.put(DetailedState.IDLE, State.DISCONNECTED)126 stateMap.put(DetailedState.IDLE, State.DISCONNECTED); stateMap.put(DetailedState.SCANNING, State.DISCONNECTED)127 stateMap.put(DetailedState.SCANNING, State.DISCONNECTED); stateMap.put(DetailedState.CONNECTING, State.CONNECTING)128 stateMap.put(DetailedState.CONNECTING, State.CONNECTING); stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING)129 stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING); stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING)130 stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING); stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING)131 stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING); stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING)132 stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING); stateMap.put(DetailedState.CONNECTED, State.CONNECTED)133 stateMap.put(DetailedState.CONNECTED, State.CONNECTED); stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED)134 stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED); stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING)135 stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING); stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED)136 stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED); stateMap.put(DetailedState.FAILED, State.DISCONNECTED)137 stateMap.put(DetailedState.FAILED, State.DISCONNECTED); stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED)138 stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED); 139 } 140 141 private int mNetworkType; 142 private int mSubtype; 143 private String mTypeName; 144 private String mSubtypeName; 145 @NonNull 146 private State mState; 147 @NonNull 148 private DetailedState mDetailedState; 149 private String mReason; 150 private String mExtraInfo; 151 private boolean mIsFailover; 152 private boolean mIsAvailable; 153 private boolean mIsRoaming; 154 155 /** 156 * Create a new instance of NetworkInfo. 157 * 158 * This may be useful for apps to write unit tests. 159 * 160 * @param type the legacy type of the network, as one of the ConnectivityManager.TYPE_* 161 * constants. 162 * @param subtype the subtype if applicable, as one of the TelephonyManager.NETWORK_TYPE_* 163 * constants. 164 * @param typeName a human-readable string for the network type, or an empty string or null. 165 * @param subtypeName a human-readable string for the subtype, or an empty string or null. 166 */ NetworkInfo(int type, @NetworkType int subtype, @Nullable String typeName, @Nullable String subtypeName)167 public NetworkInfo(int type, @NetworkType int subtype, 168 @Nullable String typeName, @Nullable String subtypeName) { 169 if (!ConnectivityManager.isNetworkTypeValid(type) 170 && type != ConnectivityManager.TYPE_NONE) { 171 throw new IllegalArgumentException("Invalid network type: " + type); 172 } 173 mNetworkType = type; 174 mSubtype = subtype; 175 mTypeName = typeName; 176 mSubtypeName = subtypeName; 177 setDetailedState(DetailedState.IDLE, null, null); 178 mState = State.UNKNOWN; 179 } 180 181 /** {@hide} */ 182 @UnsupportedAppUsage NetworkInfo(NetworkInfo source)183 public NetworkInfo(NetworkInfo source) { 184 if (source != null) { 185 synchronized (source) { 186 mNetworkType = source.mNetworkType; 187 mSubtype = source.mSubtype; 188 mTypeName = source.mTypeName; 189 mSubtypeName = source.mSubtypeName; 190 mState = source.mState; 191 mDetailedState = source.mDetailedState; 192 mReason = source.mReason; 193 mExtraInfo = source.mExtraInfo; 194 mIsFailover = source.mIsFailover; 195 mIsAvailable = source.mIsAvailable; 196 mIsRoaming = source.mIsRoaming; 197 } 198 } 199 } 200 201 /** 202 * Reports the type of network to which the 203 * info in this {@code NetworkInfo} pertains. 204 * @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link 205 * ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link 206 * ConnectivityManager#TYPE_ETHERNET}, {@link ConnectivityManager#TYPE_BLUETOOTH}, or other 207 * types defined by {@link ConnectivityManager}. 208 * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport} 209 * instead with one of the NetworkCapabilities#TRANSPORT_* constants : 210 * {@link #getType} and {@link #getTypeName} cannot account for networks using 211 * multiple transports. Note that generally apps should not care about transport; 212 * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and 213 * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that 214 * apps concerned with meteredness or bandwidth should be looking at, as they 215 * offer this information with much better accuracy. 216 */ 217 @Deprecated getType()218 public int getType() { 219 synchronized (this) { 220 return mNetworkType; 221 } 222 } 223 224 /** 225 * @deprecated Use {@link NetworkCapabilities} instead 226 * @hide 227 */ 228 @Deprecated setType(int type)229 public void setType(int type) { 230 synchronized (this) { 231 mNetworkType = type; 232 } 233 } 234 235 /** 236 * Return a network-type-specific integer describing the subtype 237 * of the network. 238 * @return the network subtype 239 * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. 240 */ 241 @Deprecated getSubtype()242 public int getSubtype() { 243 synchronized (this) { 244 return mSubtype; 245 } 246 } 247 248 /** 249 * @hide 250 */ 251 @UnsupportedAppUsage setSubtype(int subtype, String subtypeName)252 public void setSubtype(int subtype, String subtypeName) { 253 synchronized (this) { 254 mSubtype = subtype; 255 mSubtypeName = subtypeName; 256 } 257 } 258 259 /** 260 * Return a human-readable name describe the type of the network, 261 * for example "WIFI" or "MOBILE". 262 * @return the name of the network type 263 * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport} 264 * instead with one of the NetworkCapabilities#TRANSPORT_* constants : 265 * {@link #getType} and {@link #getTypeName} cannot account for networks using 266 * multiple transports. Note that generally apps should not care about transport; 267 * {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and 268 * {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that 269 * apps concerned with meteredness or bandwidth should be looking at, as they 270 * offer this information with much better accuracy. 271 */ 272 @Deprecated getTypeName()273 public String getTypeName() { 274 synchronized (this) { 275 return mTypeName; 276 } 277 } 278 279 /** 280 * Return a human-readable name describing the subtype of the network. 281 * @return the name of the network subtype 282 * @deprecated Use {@link android.telephony.TelephonyManager#getDataNetworkType} instead. 283 */ 284 @Deprecated getSubtypeName()285 public String getSubtypeName() { 286 synchronized (this) { 287 return mSubtypeName; 288 } 289 } 290 291 /** 292 * Indicates whether network connectivity exists or is in the process 293 * of being established. This is good for applications that need to 294 * do anything related to the network other than read or write data. 295 * For the latter, call {@link #isConnected()} instead, which guarantees 296 * that the network is fully usable. 297 * @return {@code true} if network connectivity exists or is in the process 298 * of being established, {@code false} otherwise. 299 * @deprecated Apps should instead use the 300 * {@link android.net.ConnectivityManager.NetworkCallback} API to 301 * learn about connectivity changes. 302 * {@link ConnectivityManager#registerDefaultNetworkCallback} and 303 * {@link ConnectivityManager#registerNetworkCallback}. These will 304 * give a more accurate picture of the connectivity state of 305 * the device and let apps react more easily and quickly to changes. 306 */ 307 @Deprecated isConnectedOrConnecting()308 public boolean isConnectedOrConnecting() { 309 synchronized (this) { 310 return mState == State.CONNECTED || mState == State.CONNECTING; 311 } 312 } 313 314 /** 315 * Indicates whether network connectivity exists and it is possible to establish 316 * connections and pass data. 317 * <p>Always call this before attempting to perform data transactions. 318 * @return {@code true} if network connectivity exists, {@code false} otherwise. 319 * @deprecated Apps should instead use the 320 * {@link android.net.ConnectivityManager.NetworkCallback} API to 321 * learn about connectivity changes. See 322 * {@link ConnectivityManager#registerDefaultNetworkCallback} and 323 * {@link ConnectivityManager#registerNetworkCallback}. These will 324 * give a more accurate picture of the connectivity state of 325 * the device and let apps react more easily and quickly to changes. 326 */ 327 @Deprecated isConnected()328 public boolean isConnected() { 329 synchronized (this) { 330 return mState == State.CONNECTED; 331 } 332 } 333 334 /** 335 * Indicates whether network connectivity is possible. A network is unavailable 336 * when a persistent or semi-persistent condition prevents the possibility 337 * of connecting to that network. Examples include 338 * <ul> 339 * <li>The device is out of the coverage area for any network of this type.</li> 340 * <li>The device is on a network other than the home network (i.e., roaming), and 341 * data roaming has been disabled.</li> 342 * <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li> 343 * </ul> 344 * Since Android L, this always returns {@code true}, because the system only 345 * returns info for available networks. 346 * @return {@code true} if the network is available, {@code false} otherwise 347 * @deprecated Apps should instead use the 348 * {@link android.net.ConnectivityManager.NetworkCallback} API to 349 * learn about connectivity changes. 350 * {@link ConnectivityManager#registerDefaultNetworkCallback} and 351 * {@link ConnectivityManager#registerNetworkCallback}. These will 352 * give a more accurate picture of the connectivity state of 353 * the device and let apps react more easily and quickly to changes. 354 */ 355 @Deprecated isAvailable()356 public boolean isAvailable() { 357 synchronized (this) { 358 return mIsAvailable; 359 } 360 } 361 362 /** 363 * Sets if the network is available, ie, if the connectivity is possible. 364 * @param isAvailable the new availability value. 365 * @deprecated Use {@link NetworkCapabilities} instead 366 * 367 * @hide 368 */ 369 @Deprecated 370 @UnsupportedAppUsage setIsAvailable(boolean isAvailable)371 public void setIsAvailable(boolean isAvailable) { 372 synchronized (this) { 373 mIsAvailable = isAvailable; 374 } 375 } 376 377 /** 378 * Indicates whether the current attempt to connect to the network 379 * resulted from the ConnectivityManager trying to fail over to this 380 * network following a disconnect from another network. 381 * @return {@code true} if this is a failover attempt, {@code false} 382 * otherwise. 383 * @deprecated This field is not populated in recent Android releases, 384 * and does not make a lot of sense in a multi-network world. 385 */ 386 @Deprecated isFailover()387 public boolean isFailover() { 388 synchronized (this) { 389 return mIsFailover; 390 } 391 } 392 393 /** 394 * Set the failover boolean. 395 * @param isFailover {@code true} to mark the current connection attempt 396 * as a failover. 397 * @deprecated This hasn't been set in any recent Android release. 398 * @hide 399 */ 400 @Deprecated 401 @UnsupportedAppUsage setFailover(boolean isFailover)402 public void setFailover(boolean isFailover) { 403 synchronized (this) { 404 mIsFailover = isFailover; 405 } 406 } 407 408 /** 409 * Indicates whether the device is currently roaming on this network. When 410 * {@code true}, it suggests that use of data on this network may incur 411 * extra costs. 412 * 413 * @return {@code true} if roaming is in effect, {@code false} otherwise. 414 * @deprecated Callers should switch to checking 415 * {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} 416 * instead, since that handles more complex situations, such as 417 * VPNs. 418 */ 419 @Deprecated isRoaming()420 public boolean isRoaming() { 421 synchronized (this) { 422 return mIsRoaming; 423 } 424 } 425 426 /** 427 * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} instead. 428 * {@hide} 429 */ 430 @VisibleForTesting 431 @Deprecated 432 @UnsupportedAppUsage setRoaming(boolean isRoaming)433 public void setRoaming(boolean isRoaming) { 434 synchronized (this) { 435 mIsRoaming = isRoaming; 436 } 437 } 438 439 /** 440 * Reports the current coarse-grained state of the network. 441 * @return the coarse-grained state 442 * @deprecated Apps should instead use the 443 * {@link android.net.ConnectivityManager.NetworkCallback} API to 444 * learn about connectivity changes. 445 * {@link ConnectivityManager#registerDefaultNetworkCallback} and 446 * {@link ConnectivityManager#registerNetworkCallback}. These will 447 * give a more accurate picture of the connectivity state of 448 * the device and let apps react more easily and quickly to changes. 449 */ 450 @Deprecated getState()451 public State getState() { 452 synchronized (this) { 453 return mState; 454 } 455 } 456 457 /** 458 * Reports the current fine-grained state of the network. 459 * @return the fine-grained state 460 * @deprecated Apps should instead use the 461 * {@link android.net.ConnectivityManager.NetworkCallback} API to 462 * learn about connectivity changes. See 463 * {@link ConnectivityManager#registerDefaultNetworkCallback} and 464 * {@link ConnectivityManager#registerNetworkCallback}. These will 465 * give a more accurate picture of the connectivity state of 466 * the device and let apps react more easily and quickly to changes. 467 */ 468 @Deprecated getDetailedState()469 public @NonNull DetailedState getDetailedState() { 470 synchronized (this) { 471 return mDetailedState; 472 } 473 } 474 475 /** 476 * Sets the fine-grained state of the network. 477 * 478 * This is only useful for testing. 479 * 480 * @param detailedState the {@link DetailedState}. 481 * @param reason a {@code String} indicating the reason for the state change, 482 * if one was supplied. May be {@code null}. 483 * @param extraInfo an optional {@code String} providing addditional network state 484 * information passed up from the lower networking layers. 485 * @deprecated Use {@link NetworkCapabilities} instead. 486 */ 487 @Deprecated setDetailedState(@onNull DetailedState detailedState, @Nullable String reason, @Nullable String extraInfo)488 public void setDetailedState(@NonNull DetailedState detailedState, @Nullable String reason, 489 @Nullable String extraInfo) { 490 synchronized (this) { 491 this.mDetailedState = detailedState; 492 this.mState = stateMap.get(detailedState); 493 this.mReason = reason; 494 this.mExtraInfo = extraInfo; 495 } 496 } 497 498 /** 499 * Set the extraInfo field. 500 * @param extraInfo an optional {@code String} providing addditional network state 501 * information passed up from the lower networking layers. 502 * @deprecated See {@link NetworkInfo#getExtraInfo}. 503 * @hide 504 */ 505 @Deprecated setExtraInfo(String extraInfo)506 public void setExtraInfo(String extraInfo) { 507 synchronized (this) { 508 this.mExtraInfo = extraInfo; 509 } 510 } 511 512 /** 513 * Report the reason an attempt to establish connectivity failed, 514 * if one is available. 515 * @return the reason for failure, or null if not available 516 * @deprecated This method does not have a consistent contract that could make it useful 517 * to callers. 518 */ getReason()519 public String getReason() { 520 synchronized (this) { 521 return mReason; 522 } 523 } 524 525 /** 526 * Report the extra information about the network state, if any was 527 * provided by the lower networking layers. 528 * @return the extra information, or null if not available 529 * @deprecated Use other services e.g. WifiManager to get additional information passed up from 530 * the lower networking layers. 531 */ 532 @Deprecated getExtraInfo()533 public String getExtraInfo() { 534 synchronized (this) { 535 return mExtraInfo; 536 } 537 } 538 539 @Override toString()540 public String toString() { 541 synchronized (this) { 542 final StringBuilder builder = new StringBuilder("["); 543 builder.append("type: ").append(getTypeName()).append("[").append(getSubtypeName()). 544 append("], state: ").append(mState).append("/").append(mDetailedState). 545 append(", reason: ").append(mReason == null ? "(unspecified)" : mReason). 546 append(", extra: ").append(mExtraInfo == null ? "(none)" : mExtraInfo). 547 append(", failover: ").append(mIsFailover). 548 append(", available: ").append(mIsAvailable). 549 append(", roaming: ").append(mIsRoaming). 550 append("]"); 551 return builder.toString(); 552 } 553 } 554 555 /** 556 * Returns a brief summary string suitable for debugging. 557 * @hide 558 */ toShortString()559 public String toShortString() { 560 synchronized (this) { 561 final StringBuilder builder = new StringBuilder(); 562 builder.append(getTypeName()); 563 564 final String subtype = getSubtypeName(); 565 if (!TextUtils.isEmpty(subtype)) { 566 builder.append("[").append(subtype).append("]"); 567 } 568 569 builder.append(" "); 570 builder.append(mDetailedState); 571 if (mIsRoaming) { 572 builder.append(" ROAMING"); 573 } 574 if (mExtraInfo != null) { 575 builder.append(" extra: ").append(mExtraInfo); 576 } 577 return builder.toString(); 578 } 579 } 580 581 @Override describeContents()582 public int describeContents() { 583 return 0; 584 } 585 586 @Override writeToParcel(Parcel dest, int flags)587 public void writeToParcel(Parcel dest, int flags) { 588 synchronized (this) { 589 dest.writeInt(mNetworkType); 590 dest.writeInt(mSubtype); 591 dest.writeString(mTypeName); 592 dest.writeString(mSubtypeName); 593 dest.writeString(mState.name()); 594 dest.writeString(mDetailedState.name()); 595 dest.writeInt(mIsFailover ? 1 : 0); 596 dest.writeInt(mIsAvailable ? 1 : 0); 597 dest.writeInt(mIsRoaming ? 1 : 0); 598 dest.writeString(mReason); 599 dest.writeString(mExtraInfo); 600 } 601 } 602 603 public static final @android.annotation.NonNull Creator<NetworkInfo> CREATOR = new Creator<NetworkInfo>() { 604 @Override 605 public NetworkInfo createFromParcel(Parcel in) { 606 int netType = in.readInt(); 607 int subtype = in.readInt(); 608 String typeName = in.readString(); 609 String subtypeName = in.readString(); 610 NetworkInfo netInfo = new NetworkInfo(netType, subtype, typeName, subtypeName); 611 netInfo.mState = State.valueOf(in.readString()); 612 netInfo.mDetailedState = DetailedState.valueOf(in.readString()); 613 netInfo.mIsFailover = in.readInt() != 0; 614 netInfo.mIsAvailable = in.readInt() != 0; 615 netInfo.mIsRoaming = in.readInt() != 0; 616 netInfo.mReason = in.readString(); 617 netInfo.mExtraInfo = in.readString(); 618 return netInfo; 619 } 620 621 @Override 622 public NetworkInfo[] newArray(int size) { 623 return new NetworkInfo[size]; 624 } 625 }; 626 } 627