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