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