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