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