1155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande/*
2155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Copyright (C) 2010 The Android Open Source Project
3155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
4155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Licensed under the Apache License, Version 2.0 (the "License");
5155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * you may not use this file except in compliance with the License.
6155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * You may obtain a copy of the License at
7155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
8155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *      http://www.apache.org/licenses/LICENSE-2.0
9155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande *
10155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Unless required by applicable law or agreed to in writing, software
11155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * distributed under the License is distributed on an "AS IS" BASIS,
12155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * See the License for the specific language governing permissions and
14155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * limitations under the License.
15155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande */
16155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
17155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandepackage com.android.server.wifi;
18155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
19155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.content.Context;
20155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.content.Intent;
21155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.SupplicantState;
22155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiConfiguration;
23155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.net.wifi.WifiManager;
24eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport android.os.BatteryStats;
25155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.os.Handler;
26155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.os.Message;
27155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.os.Parcelable;
28eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport android.os.RemoteException;
29eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport android.os.ServiceManager;
30155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.os.UserHandle;
31155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport android.util.Log;
32eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport android.util.Slog;
33eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpande
34eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport com.android.internal.app.IBatteryStats;
35eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport com.android.internal.util.State;
36eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandeimport com.android.internal.util.StateMachine;
37155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
38155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.FileDescriptor;
39155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpandeimport java.io.PrintWriter;
40155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
41155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande/**
42155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * Tracks the state changes in supplicant and provides functionality
43155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * that is based on these state changes:
44155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * - detect a failed WPA handshake that loops indefinitely
45155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande * - authentication failure handling
46155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande */
47eee1d479d8d402a2e78e2f143e957030cfc77749Vinit Deshpandepublic class SupplicantStateTracker extends StateMachine {
48155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
49155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private static final String TAG = "SupplicantStateTracker";
500888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle    private static boolean DBG = false;
51c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius    private final WifiConfigManager mWifiConfigManager;
5251991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final IBatteryStats mBatteryStats;
53155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /* Indicates authentication failure in supplicant broadcast.
54155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * TODO: enhance auth failure reporting to include notification
55155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * for all type of failures: EAP, WPS & WPA networks */
56155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private boolean mAuthFailureInSupplicantBroadcast = false;
57155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
58155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /* Maximum retries on a authentication failure notification */
59155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private static final int MAX_RETRIES_ON_AUTHENTICATION_FAILURE = 2;
60155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
61155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /* Maximum retries on assoc rejection events */
62155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private static final int MAX_RETRIES_ON_ASSOCIATION_REJECT = 16;
63155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
64155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /* Tracks if networks have been disabled during a connection */
65155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private boolean mNetworksDisabledDuringConnect = false;
66155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
6751991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final Context mContext;
68155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
6951991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mUninitializedState = new UninitializedState();
7051991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mDefaultState = new DefaultState();
7151991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mInactiveState = new InactiveState();
7251991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mDisconnectState = new DisconnectedState();
7351991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mScanState = new ScanState();
7451991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mHandshakeState = new HandshakeState();
7551991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mCompletedState = new CompletedState();
7651991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn    private final State mDormantState = new DormantState();
77155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
780888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle    void enableVerboseLogging(int verbose) {
790888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        if (verbose > 0) {
800888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle            DBG = true;
810888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        } else {
820888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle            DBG = false;
830888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle        }
840888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle    }
850888ce6f90bdaeee799dd8361ea4781e23a33b87vandwalle
86f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    public String getSupplicantStateName() {
87f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        return getCurrentState().getName();
88f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle    }
89f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
9054c9cf8d299b99f8b999bc2cf4adcda1eba81469Glen Kuhne    public SupplicantStateTracker(Context c, WifiConfigManager wcs, Handler t) {
91155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        super(TAG, t.getLooper());
92155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
93155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        mContext = c;
94c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius        mWifiConfigManager = wcs;
9551991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        mBatteryStats = (IBatteryStats)ServiceManager.getService(BatteryStats.SERVICE_NAME);
96155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        addState(mDefaultState);
97155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mUninitializedState, mDefaultState);
98155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mInactiveState, mDefaultState);
99155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mDisconnectState, mDefaultState);
100155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mScanState, mDefaultState);
101155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mHandshakeState, mDefaultState);
102155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mCompletedState, mDefaultState);
103155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            addState(mDormantState, mDefaultState);
104155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
105155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        setInitialState(mUninitializedState);
106155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        setLogRecSize(50);
107155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        setLogOnlyTransitions(true);
108155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        //start the state machine
109155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        start();
110155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
111155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
112155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void handleNetworkConnectionFailure(int netId, int disableReason) {
113f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        if (DBG) {
114f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle            Log.d(TAG, "handleNetworkConnectionFailure netId=" + Integer.toString(netId)
115f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + " reason " + Integer.toString(disableReason)
116f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle                    + " mNetworksDisabledDuringConnect=" + mNetworksDisabledDuringConnect);
117f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle        }
118f22d23092ab37286a5ef9d257d5bb32c421d2669vandwalle
119155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        /* If other networks disabled during connection, enable them */
120155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (mNetworksDisabledDuringConnect) {
121c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius            mWifiConfigManager.enableAllNetworks();
122155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            mNetworksDisabledDuringConnect = false;
123155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
1248f0f666c8bdaf508f191f8590755140b92d970eaxinhe        /* update network status */
125c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius        mWifiConfigManager.updateNetworkSelectionStatus(netId, disableReason);
126155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
127155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
128155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
129155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        SupplicantState supState = (SupplicantState) stateChangeResult.state;
130155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
131155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n");
132155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
133155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        switch (supState) {
134155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande           case DISCONNECTED:
135155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mDisconnectState);
136155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
137155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case INTERFACE_DISABLED:
138155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                //we should have received a disconnection already, do nothing
139155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
140155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case SCANNING:
141155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mScanState);
142155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
143155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case AUTHENTICATING:
144155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case ASSOCIATING:
145155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case ASSOCIATED:
146155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case FOUR_WAY_HANDSHAKE:
147155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case GROUP_HANDSHAKE:
148155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mHandshakeState);
149155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
150155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case COMPLETED:
151155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mCompletedState);
152155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
153155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case DORMANT:
154155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mDormantState);
155155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
156155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case INACTIVE:
157155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mInactiveState);
158155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
159155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case UNINITIALIZED:
160155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            case INVALID:
161155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                transitionTo(mUninitializedState);
162155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
163155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            default:
164155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                Log.e(TAG, "Unknown supplicant state " + supState);
165155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                break;
166155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
167155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
168155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
169155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth) {
17051991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        int supplState;
17151991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        switch (state) {
17251991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case DISCONNECTED: supplState = BatteryStats.WIFI_SUPPL_STATE_DISCONNECTED; break;
17351991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case INTERFACE_DISABLED:
17451991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn                supplState = BatteryStats.WIFI_SUPPL_STATE_INTERFACE_DISABLED; break;
17551991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case INACTIVE: supplState = BatteryStats.WIFI_SUPPL_STATE_INACTIVE; break;
17651991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case SCANNING: supplState = BatteryStats.WIFI_SUPPL_STATE_SCANNING; break;
17751991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case AUTHENTICATING: supplState = BatteryStats.WIFI_SUPPL_STATE_AUTHENTICATING; break;
17851991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case ASSOCIATING: supplState = BatteryStats.WIFI_SUPPL_STATE_ASSOCIATING; break;
17951991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case ASSOCIATED: supplState = BatteryStats.WIFI_SUPPL_STATE_ASSOCIATED; break;
18051991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case FOUR_WAY_HANDSHAKE:
18151991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn                supplState = BatteryStats.WIFI_SUPPL_STATE_FOUR_WAY_HANDSHAKE; break;
18251991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case GROUP_HANDSHAKE: supplState = BatteryStats.WIFI_SUPPL_STATE_GROUP_HANDSHAKE; break;
18351991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case COMPLETED: supplState = BatteryStats.WIFI_SUPPL_STATE_COMPLETED; break;
18451991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case DORMANT: supplState = BatteryStats.WIFI_SUPPL_STATE_DORMANT; break;
18551991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case UNINITIALIZED: supplState = BatteryStats.WIFI_SUPPL_STATE_UNINITIALIZED; break;
18651991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            case INVALID: supplState = BatteryStats.WIFI_SUPPL_STATE_INVALID; break;
18751991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            default:
18851991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn                Slog.w(TAG, "Unknown supplicant state " + state);
18951991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn                supplState = BatteryStats.WIFI_SUPPL_STATE_INVALID;
19051991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn                break;
19151991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        }
19251991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        try {
19351991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            mBatteryStats.noteWifiSupplicantStateChanged(supplState, failedAuth);
19451991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        } catch (RemoteException e) {
19551991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn            // Won't happen.
19651991e784c605a7432a90c9e9a91b080fb106197Dianne Hackborn        }
197155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
198155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
199155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
200155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable) state);
201155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        if (failedAuth) {
202155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            intent.putExtra(
203155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                WifiManager.EXTRA_SUPPLICANT_ERROR,
204155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                WifiManager.ERROR_AUTHENTICATING);
205155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
206155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
207155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
208155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
209155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /********************************************************
210155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * HSM states
211155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     *******************************************************/
212155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
213155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class DefaultState extends State {
214155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
215155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
216155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
217155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         }
218155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
219155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        public boolean processMessage(Message message) {
220155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
221155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            switch (message.what) {
222155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
223155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    mAuthFailureInSupplicantBroadcast = true;
224155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
225155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
226155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
227155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    SupplicantState state = stateChangeResult.state;
228155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
229155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    mAuthFailureInSupplicantBroadcast = false;
230155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    transitionOnSupplicantStateChange(stateChangeResult);
231155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
232155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
233155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    transitionTo(mUninitializedState);
234155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
235155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiManager.CONNECT_NETWORK:
236155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    mNetworksDisabledDuringConnect = true;
237155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
238155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
239155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                default:
240155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    Log.e(TAG, "Ignoring " + message);
241155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
242155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
243155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return HANDLED;
244155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
245155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
246155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
247155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    /*
248155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * This indicates that the supplicant state as seen
249155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * by the framework is not initialized yet. We are
250155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * in this state right after establishing a control
251155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * channel connection before any supplicant events
252155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * or after we have lost the control channel
253155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     * connection to the supplicant
254155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande     */
255155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class UninitializedState extends State {
256155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
257155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
258155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
259155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         }
260155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
261155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
262155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class InactiveState extends State {
263155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
264155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
265155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
266155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         }
267155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
268155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
269155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class DisconnectedState extends State {
270155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
271155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
272155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
273155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         }
274155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
275155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
276155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class ScanState extends State {
277155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
278155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
279155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
280155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         }
281155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
282155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
283155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class HandshakeState extends State {
284155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        /**
285155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * The max number of the WPA supplicant loop iterations before we
286155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         * decide that the loop should be terminated:
287155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         */
288155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
289155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        private int mLoopDetectIndex;
290155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        private int mLoopDetectCount;
291155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
292155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
293155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
294155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
295155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             mLoopDetectIndex = 0;
296155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             mLoopDetectCount = 0;
297155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         }
298155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
299155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        public boolean processMessage(Message message) {
300155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
301155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            switch (message.what) {
302155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
303155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
304155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    SupplicantState state = stateChangeResult.state;
305155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    if (SupplicantState.isHandshakeState(state)) {
306155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        if (mLoopDetectIndex > state.ordinal()) {
307155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                            mLoopDetectCount++;
308155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        }
309155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
310155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                            Log.d(TAG, "Supplicant loop detected, disabling network " +
311155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                                    stateChangeResult.networkId);
312155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                            handleNetworkConnectionFailure(stateChangeResult.networkId,
3138f0f666c8bdaf508f191f8590755140b92d970eaxinhe                                    WifiConfiguration.NetworkSelectionStatus
3148f0f666c8bdaf508f191f8590755140b92d970eaxinhe                                            .DISABLED_AUTHENTICATION_FAILURE);
315155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        }
316155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        mLoopDetectIndex = state.ordinal();
317155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        sendSupplicantStateChangedBroadcast(state,
318155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                                mAuthFailureInSupplicantBroadcast);
319155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    } else {
320155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        //Have the DefaultState handle the transition
321155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        return NOT_HANDLED;
322155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    }
323155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
324155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                default:
325155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    return NOT_HANDLED;
326155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
327155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return HANDLED;
328155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
329155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
330155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
331155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class CompletedState extends State {
332155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
333155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande         public void enter() {
334155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (DBG) Log.d(TAG, getName() + "\n");
335155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             /* Reset authentication failure count */
336155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             if (mNetworksDisabledDuringConnect) {
337c2a0ff06d58e1cfb9b69fa5b6a8fef5929812f27Roshan Pius                 mWifiConfigManager.enableAllNetworks();
338155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                 mNetworksDisabledDuringConnect = false;
339155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande             }
340155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
341155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
342155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        public boolean processMessage(Message message) {
343155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
344155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            switch(message.what) {
345155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
346155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
347155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    SupplicantState state = stateChangeResult.state;
348155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
349155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    /* Ignore any connecting state in completed state. Group re-keying
350155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                     * events and other auth events that do not affect connectivity are
351155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                     * ignored
352155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                     */
353155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    if (SupplicantState.isConnecting(state)) {
354155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                        break;
355155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    }
356155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    transitionOnSupplicantStateChange(stateChangeResult);
357155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
358155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
359155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    sendSupplicantStateChangedBroadcast(SupplicantState.DISCONNECTED, false);
360155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    transitionTo(mUninitializedState);
361155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    break;
362155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                default:
363155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande                    return NOT_HANDLED;
364155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            }
365155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            return HANDLED;
366155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
367155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
368155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
369155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    //TODO: remove after getting rid of the state in supplicant
370155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    class DormantState extends State {
371155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        @Override
372155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        public void enter() {
373155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande            if (DBG) Log.d(TAG, getName() + "\n");
374155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        }
375155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
376155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande
377155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    @Override
378155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
379155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        super.dump(fd, pw, args);
380155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        pw.println("mAuthFailureInSupplicantBroadcast " + mAuthFailureInSupplicantBroadcast);
381155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        pw.println("mNetworksDisabledDuringConnect " + mNetworksDisabledDuringConnect);
382155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande        pw.println();
383155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande    }
384155b9d09ef9b8ead3ca617afdd91e74070d3f0cbVinit Deshpande}
385