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.wifi;
18
19import android.os.Parcel;
20import android.os.Parcelable;
21
22/**
23 * From <code>defs.h</code> in <code>wpa_supplicant</code>.
24 * <p/>
25 * These enumeration values are used to indicate the current wpa_supplicant
26 * state. This is more fine-grained than most users will be interested in.
27 * In general, it is better to use
28 * {@link android.net.NetworkInfo.State NetworkInfo.State}.
29 * <p/>
30 * Note, the order of these enum constants must match the numerical values of the
31 * state constants in <code>defs.h</code> in <code>wpa_supplicant</code>.
32 */
33public enum SupplicantState implements Parcelable {
34    /**
35     * This state indicates that client is not associated, but is likely to
36     * start looking for an access point. This state is entered when a
37     * connection is lost.
38     */
39    DISCONNECTED,
40
41    /**
42     * Interface is disabled
43     * <p/>
44     * This state is entered if the network interface is disabled.
45     * wpa_supplicant refuses any new operations that would
46     * use the radio until the interface has been enabled.
47     */
48    INTERFACE_DISABLED,
49
50    /**
51     * Inactive state (wpa_supplicant disabled).
52     * <p/>
53     * This state is entered if there are no enabled networks in the
54     * configuration. wpa_supplicant is not trying to associate with a new
55     * network and external interaction (e.g., ctrl_iface call to add or
56     * enable a network) is needed to start association.
57     */
58    INACTIVE,
59
60    /**
61     * Scanning for a network.
62     * <p/>
63     * This state is entered when wpa_supplicant starts scanning for a
64     * network.
65     */
66    SCANNING,
67
68    /**
69     * Trying to authenticate with a BSS/SSID
70     * <p/>
71     * This state is entered when wpa_supplicant has found a suitable BSS
72     * to authenticate with and the driver is configured to try to
73     * authenticate with this BSS.
74     */
75    AUTHENTICATING,
76
77    /**
78     * Trying to associate with a BSS/SSID.
79     * <p/>
80     * This state is entered when wpa_supplicant has found a suitable BSS
81     * to associate with and the driver is configured to try to associate
82     * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
83     * state is entered when the driver is configured to try to associate
84     * with a network using the configured SSID and security policy.
85     */
86    ASSOCIATING,
87
88    /**
89     * Association completed.
90     * <p/>
91     * This state is entered when the driver reports that association has
92     * been successfully completed with an AP. If IEEE 802.1X is used
93     * (with or without WPA/WPA2), wpa_supplicant remains in this state
94     * until the IEEE 802.1X/EAPOL authentication has been completed.
95     */
96    ASSOCIATED,
97
98    /**
99     * WPA 4-Way Key Handshake in progress.
100     * <p/>
101     * This state is entered when WPA/WPA2 4-Way Handshake is started. In
102     * case of WPA-PSK, this happens when receiving the first EAPOL-Key
103     * frame after association. In case of WPA-EAP, this state is entered
104     * when the IEEE 802.1X/EAPOL authentication has been completed.
105     */
106    FOUR_WAY_HANDSHAKE,
107
108    /**
109     * WPA Group Key Handshake in progress.
110     * <p/>
111     * This state is entered when 4-Way Key Handshake has been completed
112     * (i.e., when the supplicant sends out message 4/4) and when Group
113     * Key rekeying is started by the AP (i.e., when supplicant receives
114     * message 1/2).
115     */
116    GROUP_HANDSHAKE,
117
118    /**
119     * All authentication completed.
120     * <p/>
121     * This state is entered when the full authentication process is
122     * completed. In case of WPA2, this happens when the 4-Way Handshake is
123     * successfully completed. With WPA, this state is entered after the
124     * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
125     * completed after dynamic keys are received (or if not used, after
126     * the EAP authentication has been completed). With static WEP keys and
127     * plaintext connections, this state is entered when an association
128     * has been completed.
129     * <p/>
130     * This state indicates that the supplicant has completed its
131     * processing for the association phase and that data connection is
132     * fully configured. Note, however, that there may not be any IP
133     * address associated with the connection yet. Typically, a DHCP
134     * request needs to be sent at this point to obtain an address.
135     */
136    COMPLETED,
137
138    /**
139     * An Android-added state that is reported when a client issues an
140     * explicit DISCONNECT command. In such a case, the supplicant is
141     * not only dissociated from the current access point (as for the
142     * DISCONNECTED state above), but it also does not attempt to connect
143     * to any access point until a RECONNECT or REASSOCIATE command
144     * is issued by the client.
145     */
146    DORMANT,
147
148    /**
149     * No connection to wpa_supplicant.
150     * <p/>
151     * This is an additional pseudo-state to handle the case where
152     * wpa_supplicant is not running and/or we have not been able
153     * to establish a connection to it.
154     */
155    UNINITIALIZED,
156
157    /**
158     * A pseudo-state that should normally never be seen.
159     */
160    INVALID;
161
162    /**
163     * Returns {@code true} if the supplicant state is valid and {@code false}
164     * otherwise.
165     * @param state The supplicant state
166     * @return {@code true} if the supplicant state is valid and {@code false}
167     * otherwise.
168     */
169    public static boolean isValidState(SupplicantState state) {
170        return state != UNINITIALIZED && state != INVALID;
171    }
172
173
174    /** Supplicant associating or authenticating is considered a handshake state {@hide} */
175    public static boolean isHandshakeState(SupplicantState state) {
176        switch(state) {
177            case AUTHENTICATING:
178            case ASSOCIATING:
179            case ASSOCIATED:
180            case FOUR_WAY_HANDSHAKE:
181            case GROUP_HANDSHAKE:
182                return true;
183            case COMPLETED:
184            case DISCONNECTED:
185            case INTERFACE_DISABLED:
186            case INACTIVE:
187            case SCANNING:
188            case DORMANT:
189            case UNINITIALIZED:
190            case INVALID:
191                return false;
192            default:
193                throw new IllegalArgumentException("Unknown supplicant state");
194        }
195    }
196
197    static boolean isConnecting(SupplicantState state) {
198        switch(state) {
199            case AUTHENTICATING:
200            case ASSOCIATING:
201            case ASSOCIATED:
202            case FOUR_WAY_HANDSHAKE:
203            case GROUP_HANDSHAKE:
204            case COMPLETED:
205                return true;
206            case DISCONNECTED:
207            case INTERFACE_DISABLED:
208            case INACTIVE:
209            case SCANNING:
210            case DORMANT:
211            case UNINITIALIZED:
212            case INVALID:
213                return false;
214            default:
215                throw new IllegalArgumentException("Unknown supplicant state");
216        }
217    }
218
219    static boolean isDriverActive(SupplicantState state) {
220        switch(state) {
221            case DISCONNECTED:
222            case DORMANT:
223            case INACTIVE:
224            case AUTHENTICATING:
225            case ASSOCIATING:
226            case ASSOCIATED:
227            case SCANNING:
228            case FOUR_WAY_HANDSHAKE:
229            case GROUP_HANDSHAKE:
230            case COMPLETED:
231                return true;
232            case INTERFACE_DISABLED:
233            case UNINITIALIZED:
234            case INVALID:
235                return false;
236            default:
237                throw new IllegalArgumentException("Unknown supplicant state");
238        }
239    }
240
241    /** Implement the Parcelable interface {@hide} */
242    public int describeContents() {
243        return 0;
244    }
245
246    /** Implement the Parcelable interface {@hide} */
247    public void writeToParcel(Parcel dest, int flags) {
248        dest.writeString(name());
249    }
250
251    /** Implement the Parcelable interface {@hide} */
252    public static final Creator<SupplicantState> CREATOR =
253        new Creator<SupplicantState>() {
254            public SupplicantState createFromParcel(Parcel in) {
255                return SupplicantState.valueOf(in.readString());
256            }
257
258            public SupplicantState[] newArray(int size) {
259                return new SupplicantState[size];
260            }
261        };
262
263}
264