119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff/*
219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * Copyright (C) 2010 The Android Open Source Project
319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff *
419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License");
519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * you may not use this file except in compliance with the License.
619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * You may obtain a copy of the License at
719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff *
819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff *      http://www.apache.org/licenses/LICENSE-2.0
919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff *
1019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * Unless required by applicable law or agreed to in writing, software
1119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS,
1219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * See the License for the specific language governing permissions and
1419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * limitations under the License.
1519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff */
1619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
1719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffpackage android.net.wifi;
1819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
1964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleimport com.android.internal.util.State;
2064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleimport com.android.internal.util.StateMachine;
2119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
2255bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo syncimport android.net.wifi.StateChangeResult;
2319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffimport android.content.Context;
2419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffimport android.content.Intent;
2519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffimport android.os.Handler;
2619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffimport android.os.Message;
2719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffimport android.os.Parcelable;
285ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
2919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriffimport android.util.Log;
3019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
3119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff/**
3219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * Tracks the state changes in supplicant and provides functionality
3319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * that is based on these state changes:
3419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff * - detect a failed WPA handshake that loops indefinitely
35b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff * - authentication failure handling
3619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff */
3764c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Savilleclass SupplicantStateTracker extends StateMachine {
3819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
3919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    private static final String TAG = "SupplicantStateTracker";
4019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    private static final boolean DBG = false;
4119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
4219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    private WifiStateMachine mWifiStateMachine;
43fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff    private WifiConfigStore mWifiConfigStore;
44b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff    private int mAuthenticationFailuresCount = 0;
4519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    /* Indicates authentication failure in supplicant broadcast.
4619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff     * TODO: enhance auth failure reporting to include notification
4719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff     * for all type of failures: EAP, WPS & WPA networks */
4819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    private boolean mAuthFailureInSupplicantBroadcast = false;
4919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
50b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff    /* Maximum retries on a authentication failure notification */
51b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff    private static final int MAX_RETRIES_ON_AUTHENTICATION_FAILURE = 2;
5219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
538e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff    /* Tracks if networks have been disabled during a connection */
548e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff    private boolean mNetworksDisabledDuringConnect = false;
558e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff
5619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    private Context mContext;
5719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
5864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mUninitializedState = new UninitializedState();
5964c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mDefaultState = new DefaultState();
6064c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mInactiveState = new InactiveState();
6164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mDisconnectState = new DisconnectedState();
6264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mScanState = new ScanState();
6364c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mHandshakeState = new HandshakeState();
6464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mCompletedState = new CompletedState();
6564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    private State mDormantState = new DormantState();
6619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
67fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff    public SupplicantStateTracker(Context c, WifiStateMachine wsm, WifiConfigStore wcs, Handler t) {
68fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        super(TAG, t.getLooper());
6919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
70fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mContext = c;
7119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        mWifiStateMachine = wsm;
72fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiConfigStore = wcs;
7319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        addState(mDefaultState);
7419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mUninitializedState, mDefaultState);
7519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mInactiveState, mDefaultState);
7619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mDisconnectState, mDefaultState);
7719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mScanState, mDefaultState);
7819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mHandshakeState, mDefaultState);
7919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mCompletedState, mDefaultState);
8019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            addState(mDormantState, mDefaultState);
8119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
8219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        setInitialState(mUninitializedState);
8319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
8419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        //start the state machine
8519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        start();
8619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
8719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
888e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff    private void handleNetworkConnectionFailure(int netId) {
898e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff        /* If other networks disabled during connection, enable them */
908e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff        if (mNetworksDisabledDuringConnect) {
91fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff            mWifiConfigStore.enableAllNetworks();
928e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff            mNetworksDisabledDuringConnect = false;
938e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff        }
948e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff        /* Disable failed network */
95fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff        mWifiConfigStore.disableNetwork(netId, WifiConfiguration.DISABLED_AUTH_FAILURE);
968e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff    }
978e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff
9819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
9919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        SupplicantState supState = (SupplicantState) stateChangeResult.state;
10019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
10119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n");
10219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
10319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        switch (supState) {
104319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff           case DISCONNECTED:
10519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mDisconnectState);
10619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
107319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff            case INTERFACE_DISABLED:
108319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                //we should have received a disconnection already, do nothing
109319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                break;
11019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case SCANNING:
11119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mScanState);
11219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
113319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff            case AUTHENTICATING:
11419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case ASSOCIATING:
11519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case ASSOCIATED:
11619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case FOUR_WAY_HANDSHAKE:
11719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case GROUP_HANDSHAKE:
11819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mHandshakeState);
11919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
12019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case COMPLETED:
12119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mCompletedState);
12219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
12319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case DORMANT:
12419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mDormantState);
12519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
12619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case INACTIVE:
12719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mInactiveState);
12819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
12919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case UNINITIALIZED:
13019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            case INVALID:
13119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                transitionTo(mUninitializedState);
13219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
13319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            default:
13419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                Log.e(TAG, "Unknown supplicant state " + supState);
13519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                break;
13619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        }
13719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
13819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
139b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff    private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth) {
14019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
14119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
14219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
143b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable) state);
14419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        if (failedAuth) {
14519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            intent.putExtra(
14619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                WifiManager.EXTRA_SUPPLICANT_ERROR,
14719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                WifiManager.ERROR_AUTHENTICATING);
14819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        }
1495ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
15019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
15119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
15219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    /********************************************************
15319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff     * HSM states
15419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff     *******************************************************/
15519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
15664c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class DefaultState extends State {
15719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
15819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
15919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
16019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         }
16119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
16219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        public boolean processMessage(Message message) {
16319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
16419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            switch (message.what) {
16555bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
166b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff                    mAuthenticationFailuresCount++;
16719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    mAuthFailureInSupplicantBroadcast = true;
16819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    break;
16955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
17019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
171b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    SupplicantState state = stateChangeResult.state;
172b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
17319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    mAuthFailureInSupplicantBroadcast = false;
17419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    transitionOnSupplicantStateChange(stateChangeResult);
17519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    break;
176b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
177b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    transitionTo(mUninitializedState);
178b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    break;
179d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                case WifiManager.CONNECT_NETWORK:
1808e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff                    mNetworksDisabledDuringConnect = true;
1818e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff                    break;
18219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                default:
18319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    Log.e(TAG, "Ignoring " + message);
18419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    break;
18519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            }
18619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            return HANDLED;
18719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        }
18819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
18919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
190b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff    /*
191b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     * This indicates that the supplicant state as seen
192b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     * by the framework is not initialized yet. We are
193b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     * in this state right after establishing a control
194b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     * channel connection before any supplicant events
195b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     * or after we have lost the control channel
196b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     * connection to the supplicant
197b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff     */
19864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class UninitializedState extends State {
19919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
20019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
20119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
20219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         }
20319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
20419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
20564c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class InactiveState extends State {
20619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
20719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
20819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
20919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         }
21019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
21119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
21264c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class DisconnectedState extends State {
21319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
21419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
21519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
216b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff             /* If a disconnect event happens after authentication failure
21719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff              * exceeds maximum retries, disable the network
21819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff              */
21919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             Message message = getCurrentMessage();
22019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
22119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
222b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff             if (mAuthenticationFailuresCount >= MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
22319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                 Log.d(TAG, "Failed to authenticate, disabling network " +
22419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                         stateChangeResult.networkId);
2258e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff                 handleNetworkConnectionFailure(stateChangeResult.networkId);
226b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff                 mAuthenticationFailuresCount = 0;
22719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             }
22819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         }
22919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
23019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
23164c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class ScanState extends State {
23219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
23319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
23419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
23519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         }
23619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
23719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
23864c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class HandshakeState extends State {
23919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        /**
24019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         * The max number of the WPA supplicant loop iterations before we
24119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         * decide that the loop should be terminated:
24219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         */
24319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        private static final int MAX_SUPPLICANT_LOOP_ITERATIONS = 4;
24419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        private int mLoopDetectIndex;
24519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        private int mLoopDetectCount;
24619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
24719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
24819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
24919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
25019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             mLoopDetectIndex = 0;
25119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             mLoopDetectCount = 0;
25219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         }
25319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
25419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        public boolean processMessage(Message message) {
25519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
25619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            switch (message.what) {
25755bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
25819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
259b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    SupplicantState state = stateChangeResult.state;
260319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                    if (SupplicantState.isHandshakeState(state)) {
26119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        if (mLoopDetectIndex > state.ordinal()) {
26219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                            mLoopDetectCount++;
26319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        }
26419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        if (mLoopDetectCount > MAX_SUPPLICANT_LOOP_ITERATIONS) {
26519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                            Log.d(TAG, "Supplicant loop detected, disabling network " +
26619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                                    stateChangeResult.networkId);
2678e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff                            handleNetworkConnectionFailure(stateChangeResult.networkId);
26819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        }
26919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        mLoopDetectIndex = state.ordinal();
270b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                        sendSupplicantStateChangedBroadcast(state,
27119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                                mAuthFailureInSupplicantBroadcast);
27219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    } else {
27319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        //Have the DefaultState handle the transition
27419d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        return NOT_HANDLED;
27519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    }
27619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    break;
27719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                default:
27819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    return NOT_HANDLED;
27919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            }
28019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            return HANDLED;
28119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        }
28219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
28319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
28464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class CompletedState extends State {
28519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
28619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff         public void enter() {
28719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff             if (DBG) Log.d(TAG, getName() + "\n");
288b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff             /* Reset authentication failure count */
289b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff             mAuthenticationFailuresCount = 0;
2908e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff             if (mNetworksDisabledDuringConnect) {
291fc7f95abcda6fa35c175f9225358ea75c22952abIrfan Sheriff                 mWifiConfigStore.enableAllNetworks();
2928e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff                 mNetworksDisabledDuringConnect = false;
2938e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff             }
2948e86b89860114386e6c43f55fc034a26798b73e2Irfan Sheriff        }
29519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
29619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        public boolean processMessage(Message message) {
29719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
29819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            switch(message.what) {
29955bc5f3e0408bcb5a39a6732de0b2d1aa99a55berepo sync                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
30019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
301b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    SupplicantState state = stateChangeResult.state;
302b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
303319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                    /* Ignore any connecting state in completed state. Group re-keying
304319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                     * events and other auth events that do not affect connectivity are
305319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                     * ignored
306319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                     */
307319da8c4c59be36fe2e221a0aba230ef6b77a14fIrfan Sheriff                    if (SupplicantState.isConnecting(state)) {
30819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                        break;
30919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    }
31019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    transitionOnSupplicantStateChange(stateChangeResult);
31119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    break;
312b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
313b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    sendSupplicantStateChangedBroadcast(SupplicantState.DISCONNECTED, false);
314b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    transitionTo(mUninitializedState);
315b45e726bf5df9650e8a67a7c05bf2f41f414c07dIrfan Sheriff                    break;
31619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                default:
31719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff                    return NOT_HANDLED;
31819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            }
31919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            return HANDLED;
32019d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        }
32119d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
32219d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff
32319d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    //TODO: remove after getting rid of the state in supplicant
32464c42cae4482fe0157e977b8ddd0f2c2436b3f31Wink Saville    class DormantState extends State {
32519d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        @Override
32619d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        public void enter() {
32719d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff            if (DBG) Log.d(TAG, getName() + "\n");
32819d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff        }
32919d245b792e1d941fbba9b04ae20ce9d6e6e18f8Irfan Sheriff    }
3306bb7652b47b7c3068fa5e20a20263e651180c856Irfan Sheriff}
331