Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b45e726b authored by Irfan Sheriff's avatar Irfan Sheriff
Browse files

Fix wifi broadcasts

Add the missing wifi disable broadcast and also send out
supplicant disconnect on shutdown.

Added unit test cases.

Bug: 3294055

Change-Id: Ia56a8ec9d17784c5aac5b8b369c04837f9057c54
parent 3d808115
Loading
Loading
Loading
Loading
+88 −0
Original line number Original line Diff line number Diff line
@@ -18,14 +18,17 @@ package com.android.connectivitymanagertest.unit;


import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Context;
import android.content.Context;
import android.app.Instrumentation;
import android.app.Instrumentation;
import android.os.Handler;
import android.os.Handler;
import android.os.Message;
import android.os.Message;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.SupplicantState;


import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.AndroidTestCase;
import android.test.AndroidTestCase;
@@ -45,10 +48,62 @@ public class WifiClientTest extends AndroidTestCase {


    //10s delay for turning on wifi
    //10s delay for turning on wifi
    private static final int DELAY = 10000;
    private static final int DELAY = 10000;
    private WifiStateListener mWifiStateListener;
    int mWifiState;
    int mDisableBroadcastCounter = 0;
    int mEnableBroadcastCounter = 0;
    NetworkInfo mNetworkInfo;
    boolean mSupplicantConnection;
    SupplicantState mSupplicantState;

    private class WifiStateListener extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                        WifiManager.WIFI_STATE_UNKNOWN);
                switch (mWifiState) {
                    case WifiManager.WIFI_STATE_DISABLING:
                        if (mDisableBroadcastCounter == 0) mDisableBroadcastCounter++;
                        break;
                    case WifiManager.WIFI_STATE_DISABLED:
                        if (mDisableBroadcastCounter == 1) mDisableBroadcastCounter++;
                        break;
                    case WifiManager.WIFI_STATE_ENABLING:
                        if (mEnableBroadcastCounter == 0) mEnableBroadcastCounter++;
                        break;
                    case WifiManager.WIFI_STATE_ENABLED:
                        if (mEnableBroadcastCounter == 1) mEnableBroadcastCounter++;
                        break;
                }
            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
                mNetworkInfo = (NetworkInfo)
                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
                mSupplicantState = (SupplicantState)
                        intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE);
            } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
                mSupplicantConnection =
                        intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false);
            }
        }
    }


    @Override
    @Override
    protected void setUp() throws Exception {
    protected void setUp() throws Exception {
        super.setUp();
        super.setUp();

        // register a connectivity receiver for CONNECTIVITY_ACTION;

        mWifiStateListener = new WifiStateListener();
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        getContext().registerReceiver(mWifiStateListener, mIntentFilter);

        mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
        mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
        mWifiManager.setWifiEnabled(true);
        mWifiManager.setWifiEnabled(true);
        assertNotNull(mWifiManager);
        assertNotNull(mWifiManager);
@@ -183,4 +238,37 @@ public class WifiClientTest extends AndroidTestCase {
        assertTrue(ret);
        assertTrue(ret);
        mWifiManager.saveConfiguration();
        mWifiManager.saveConfiguration();
    }
    }

    // Test case 5: test wifi state change broadcasts
    @LargeTest
    public void testWifiBroadcasts() {

        /* Initialize */
        mWifiManager.setWifiEnabled(false);
        sleepAfterWifiEnable();
        mDisableBroadcastCounter = 0;
        mEnableBroadcastCounter = 0;
        mSupplicantConnection = false;
        mNetworkInfo = null;
        mSupplicantState = null;

        /* Enable wifi */
        mWifiManager.setWifiEnabled(true);
        sleepAfterWifiEnable();
        assertTrue(mEnableBroadcastCounter == 2);
        assertTrue(mSupplicantConnection == true);
        assertTrue(mNetworkInfo.isConnected());
        assertTrue(mSupplicantState == SupplicantState.COMPLETED);


        /* Disable wifi */
        mWifiManager.setWifiEnabled(false);
        sleepAfterWifiEnable();
        assertTrue(mDisableBroadcastCounter == 2);
        assertTrue(mSupplicantConnection == false);
        assertTrue(!mNetworkInfo.isConnected());
        assertTrue(mSupplicantState != SupplicantState.COMPLETED);

    }

}
}
+23 −14
Original line number Original line Diff line number Diff line
@@ -79,11 +79,6 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
        start();
        start();
    }
    }


    public void resetSupplicantState() {
        transitionTo(mUninitializedState);
    }


    private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
    private void transitionOnSupplicantStateChange(StateChangeResult stateChangeResult) {
        SupplicantState supState = (SupplicantState) stateChangeResult.state;
        SupplicantState supState = (SupplicantState) stateChangeResult.state;


@@ -121,11 +116,11 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
        }
        }
    }
    }


    private void sendSupplicantStateChangedBroadcast(StateChangeResult sc, boolean failedAuth) {
    private void sendSupplicantStateChangedBroadcast(SupplicantState state, boolean failedAuth) {
        Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        Intent intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable)sc.state);
        intent.putExtra(WifiManager.EXTRA_NEW_STATE, (Parcelable) state);
        if (failedAuth) {
        if (failedAuth) {
            intent.putExtra(
            intent.putExtra(
                WifiManager.EXTRA_SUPPLICANT_ERROR,
                WifiManager.EXTRA_SUPPLICANT_ERROR,
@@ -153,11 +148,14 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
                    break;
                    break;
                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    sendSupplicantStateChangedBroadcast(stateChangeResult,
                    SupplicantState state = stateChangeResult.state;
                            mAuthFailureInSupplicantBroadcast);
                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
                    mAuthFailureInSupplicantBroadcast = false;
                    mAuthFailureInSupplicantBroadcast = false;
                    transitionOnSupplicantStateChange(stateChangeResult);
                    transitionOnSupplicantStateChange(stateChangeResult);
                    break;
                    break;
                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
                    transitionTo(mUninitializedState);
                    break;
                default:
                default:
                    Log.e(TAG, "Ignoring " + message);
                    Log.e(TAG, "Ignoring " + message);
                    break;
                    break;
@@ -166,6 +164,14 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
        }
        }
    }
    }


    /*
     * This indicates that the supplicant state as seen
     * by the framework is not initialized yet. We are
     * in this state right after establishing a control
     * channel connection before any supplicant events
     * or after we have lost the control channel
     * connection to the supplicant
     */
    class UninitializedState extends HierarchicalState {
    class UninitializedState extends HierarchicalState {
        @Override
        @Override
         public void enter() {
         public void enter() {
@@ -239,7 +245,7 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
            switch (message.what) {
            switch (message.what) {
                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    SupplicantState state = (SupplicantState) stateChangeResult.state;
                    SupplicantState state = stateChangeResult.state;
                    if (state == SupplicantState.ASSOCIATING ||
                    if (state == SupplicantState.ASSOCIATING ||
                            state == SupplicantState.ASSOCIATED ||
                            state == SupplicantState.ASSOCIATED ||
                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
@@ -253,7 +259,7 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
                            WifiConfigStore.disableNetwork(stateChangeResult.networkId);
                            WifiConfigStore.disableNetwork(stateChangeResult.networkId);
                        }
                        }
                        mLoopDetectIndex = state.ordinal();
                        mLoopDetectIndex = state.ordinal();
                        sendSupplicantStateChangedBroadcast(stateChangeResult,
                        sendSupplicantStateChangedBroadcast(state,
                                mAuthFailureInSupplicantBroadcast);
                                mAuthFailureInSupplicantBroadcast);
                    } else {
                    } else {
                        //Have the DefaultState handle the transition
                        //Have the DefaultState handle the transition
@@ -280,9 +286,8 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
            switch(message.what) {
            switch(message.what) {
                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    SupplicantState state = (SupplicantState) stateChangeResult.state;
                    SupplicantState state = stateChangeResult.state;
                    sendSupplicantStateChangedBroadcast(stateChangeResult,
                    sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
                            mAuthFailureInSupplicantBroadcast);
                    /* Ignore a re-auth in completed state */
                    /* Ignore a re-auth in completed state */
                    if (state == SupplicantState.ASSOCIATING ||
                    if (state == SupplicantState.ASSOCIATING ||
                            state == SupplicantState.ASSOCIATED ||
                            state == SupplicantState.ASSOCIATED ||
@@ -293,6 +298,10 @@ class SupplicantStateTracker extends HierarchicalStateMachine {
                    }
                    }
                    transitionOnSupplicantStateChange(stateChangeResult);
                    transitionOnSupplicantStateChange(stateChangeResult);
                    break;
                    break;
                case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE:
                    sendSupplicantStateChangedBroadcast(SupplicantState.DISCONNECTED, false);
                    transitionTo(mUninitializedState);
                    break;
                default:
                default:
                    return NOT_HANDLED;
                    return NOT_HANDLED;
            }
            }
+25 −25
Original line number Original line Diff line number Diff line
@@ -326,9 +326,12 @@ public class WifiStateMachine extends HierarchicalStateMachine {
    /* Set the frequency band */
    /* Set the frequency band */
    static final int CMD_SET_FREQUENCY_BAND               = 90;
    static final int CMD_SET_FREQUENCY_BAND               = 90;


    /* Commands from the SupplicantStateTracker */
    /* Commands from/to the SupplicantStateTracker */
    /* Indicates whether a wifi network is available for connection */
    /* Indicates whether a wifi network is available for connection */
    static final int CMD_SET_NETWORK_AVAILABLE            = 111;
    static final int CMD_SET_NETWORK_AVAILABLE            = 111;
    /* Reset the supplicant state tracker */
    static final int CMD_RESET_SUPPLICANT_STATE           = 112;



    /* Commands/events reported by WpsStateMachine */
    /* Commands/events reported by WpsStateMachine */
    /* Indicates the completion of WPS activity */
    /* Indicates the completion of WPS activity */
@@ -1453,20 +1456,17 @@ public class WifiStateMachine extends HierarchicalStateMachine {
     ********************************************************/
     ********************************************************/


    /**
    /**
     * A structure for supplying information about a supplicant state
     * Stores supplicant state change information passed from WifiMonitor
     * change in the STATE_CHANGE event message that comes from the
     * WifiMonitor
     * thread.
     */
     */
    static class StateChangeResult {
    static class StateChangeResult {
        StateChangeResult(int networkId, String BSSID, Object state) {
        StateChangeResult(int networkId, String BSSID, SupplicantState state) {
            this.state = state;
            this.state = state;
            this.BSSID = BSSID;
            this.BSSID = BSSID;
            this.networkId = networkId;
            this.networkId = networkId;
        }
        }
        int networkId;
        int networkId;
        String BSSID;
        String BSSID;
        Object state;
        SupplicantState state;
    }
    }


    /**
    /**
@@ -1505,11 +1505,9 @@ public class WifiStateMachine extends HierarchicalStateMachine {
     */
     */
    void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) {
    void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) {
        if (newState == NetworkInfo.DetailedState.CONNECTED) {
        if (newState == NetworkInfo.DetailedState.CONNECTED) {
            sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT,
            sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT, networkId, 0, BSSID));
                    new StateChangeResult(networkId, BSSID, newState)));
        } else {
        } else {
            sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT,
            sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT, networkId, 0, BSSID));
                    new StateChangeResult(networkId, BSSID, newState)));
        }
        }
    }
    }


@@ -1755,7 +1753,6 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                    if(WifiNative.startSupplicant()) {
                    if(WifiNative.startSupplicant()) {
                        Log.d(TAG, "Supplicant start successful");
                        Log.d(TAG, "Supplicant start successful");
                        mWifiMonitor.startMonitoring();
                        mWifiMonitor.startMonitoring();
                        setWifiState(WIFI_STATE_ENABLED);
                        transitionTo(mSupplicantStartingState);
                        transitionTo(mSupplicantStartingState);
                    } else {
                    } else {
                        Log.e(TAG, "Failed to start supplicant!");
                        Log.e(TAG, "Failed to start supplicant!");
@@ -1914,8 +1911,11 @@ public class WifiStateMachine extends HierarchicalStateMachine {
            switch(message.what) {
            switch(message.what) {
                case SUP_CONNECTION_EVENT:
                case SUP_CONNECTION_EVENT:
                    Log.d(TAG, "Supplicant connection established");
                    Log.d(TAG, "Supplicant connection established");
                    setWifiState(WIFI_STATE_ENABLED);
                    mSupplicantRestartCount = 0;
                    mSupplicantRestartCount = 0;
                    mSupplicantStateTracker.resetSupplicantState();
                    /* Reset the supplicant state to indicate the supplicant
                     * state is not known at this time */
                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                    /* Initialize data structures */
                    /* Initialize data structures */
                    mLastBssid = null;
                    mLastBssid = null;
                    mLastNetworkId = -1;
                    mLastNetworkId = -1;
@@ -1944,7 +1944,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                        Log.e(TAG, "Failed " + mSupplicantRestartCount +
                        Log.e(TAG, "Failed " + mSupplicantRestartCount +
                                " times to start supplicant, unload driver");
                                " times to start supplicant, unload driver");
                        transitionTo(mDriverLoadedState);
                        transitionTo(mDriverLoadedState);
                        sendMessage(CMD_UNLOAD_DRIVER);
                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
                    }
                    }
                    break;
                    break;
                case CMD_LOAD_DRIVER:
                case CMD_LOAD_DRIVER:
@@ -1995,8 +1995,9 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                        WifiNative.killSupplicant();
                        WifiNative.killSupplicant();
                    }
                    }
                    handleNetworkDisconnect();
                    handleNetworkDisconnect();
                    setWifiState(WIFI_STATE_DISABLING);
                    sendSupplicantConnectionChangedBroadcast(false);
                    sendSupplicantConnectionChangedBroadcast(false);
                    mSupplicantStateTracker.resetSupplicantState();
                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                    transitionTo(mSupplicantStoppingState);
                    transitionTo(mSupplicantStoppingState);
                    break;
                    break;
                case SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
                case SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
@@ -2006,7 +2007,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                    WifiNative.closeSupplicantConnection();
                    WifiNative.closeSupplicantConnection();
                    handleNetworkDisconnect();
                    handleNetworkDisconnect();
                    sendSupplicantConnectionChangedBroadcast(false);
                    sendSupplicantConnectionChangedBroadcast(false);
                    mSupplicantStateTracker.resetSupplicantState();
                    mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
                    transitionTo(mDriverLoadedState);
                    transitionTo(mDriverLoadedState);
                    sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                    sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                    break;
                    break;
@@ -2380,7 +2381,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                    break;
                    break;
                case SUPPLICANT_STATE_CHANGE_EVENT:
                case SUPPLICANT_STATE_CHANGE_EVENT:
                    stateChangeResult = (StateChangeResult) message.obj;
                    stateChangeResult = (StateChangeResult) message.obj;
                    SupplicantState state = (SupplicantState) stateChangeResult.state;
                    SupplicantState state = stateChangeResult.state;
                    // Supplicant state change
                    // Supplicant state change
                    // [31-13] Reserved for future use
                    // [31-13] Reserved for future use
                    // [8 - 0] Supplicant state (as defined in SupplicantState.java)
                    // [8 - 0] Supplicant state (as defined in SupplicantState.java)
@@ -2445,13 +2446,13 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                    return NOT_HANDLED;
                    return NOT_HANDLED;
                case NETWORK_CONNECTION_EVENT:
                case NETWORK_CONNECTION_EVENT:
                    Log.d(TAG,"Network connection established");
                    Log.d(TAG,"Network connection established");
                    stateChangeResult = (StateChangeResult) message.obj;
                    mLastNetworkId = message.arg1;
                    mLastBssid = (String) message.obj;


                    //TODO: make supplicant modification to push this in events
                    //TODO: make supplicant modification to push this in events
                    mWifiInfo.setSSID(fetchSSID());
                    mWifiInfo.setSSID(fetchSSID());
                    mWifiInfo.setBSSID(mLastBssid = stateChangeResult.BSSID);
                    mWifiInfo.setBSSID(mLastBssid);
                    mWifiInfo.setNetworkId(stateChangeResult.networkId);
                    mWifiInfo.setNetworkId(mLastNetworkId);
                    mLastNetworkId = stateChangeResult.networkId;
                    /* send event to CM & network change broadcast */
                    /* send event to CM & network change broadcast */
                    setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
                    setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
                    sendNetworkStateChangeBroadcast(mLastBssid);
                    sendNetworkStateChangeBroadcast(mLastBssid);
@@ -2825,8 +2826,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                    break;
                    break;
                case SUPPLICANT_STATE_CHANGE_EVENT:
                case SUPPLICANT_STATE_CHANGE_EVENT:
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                    SupplicantState state = (SupplicantState) stateChangeResult.state;
                    setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
                    setNetworkDetailedState(WifiInfo.getDetailedStateOf(state));
                    /* DriverStartedState does the rest of the handling */
                    /* DriverStartedState does the rest of the handling */
                    return NOT_HANDLED;
                    return NOT_HANDLED;
                default:
                default: