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

Commit 96071a70 authored by Irfan Sheriff's avatar Irfan Sheriff
Browse files

Handle supplicant stop correctly

- Use a clean terminate for a regular stop and on failure kill supplicant. This prevents
WifiMonitor from getting hung permanently on a socket in case of a kill

- When WifiMonitor exits, kill supplicant and cleanup sockets

Change-Id: I87c32e03d945433f33eed8c326d7f0368925bf55
parent 2bc248b6
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz)
    return (jboolean)(::wifi_start_supplicant() == 0);
}

static jboolean android_net_wifi_stopSupplicant(JNIEnv* env, jobject clazz)
static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject clazz)
{
    return (jboolean)(::wifi_stop_supplicant() == 0);
}
@@ -533,6 +533,11 @@ static jboolean android_net_wifi_reloadConfigCommand(JNIEnv* env, jobject clazz)
    return doBooleanCommand("RECONFIGURE", "OK");
}

static jboolean android_net_wifi_terminateCommand(JNIEnv* env, jobject clazz)
{
    return doBooleanCommand("TERMINATE", "OK");
}

static jboolean android_net_wifi_setScanResultHandlingCommand(JNIEnv* env, jobject clazz, jint mode)
{
    char cmdstr[BUF_SIZE];
@@ -605,7 +610,7 @@ static JNINativeMethod gWifiMethods[] = {
    { "isDriverLoaded", "()Z",  (void *)android_net_wifi_isDriverLoaded},
    { "unloadDriver", "()Z",  (void *)android_net_wifi_unloadDriver },
    { "startSupplicant", "()Z",  (void *)android_net_wifi_startSupplicant },
    { "stopSupplicant", "()Z",  (void *)android_net_wifi_stopSupplicant },
    { "killSupplicant", "()Z",  (void *)android_net_wifi_killSupplicant },
    { "connectToSupplicant", "()Z",  (void *)android_net_wifi_connectToSupplicant },
    { "closeSupplicantConnection", "()V",  (void *)android_net_wifi_closeSupplicantConnection },

@@ -647,6 +652,7 @@ static JNINativeMethod gWifiMethods[] = {
    { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand },
    { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand },
    { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand },
    { "terminateCommand", "()Z", (void*) android_net_wifi_terminateCommand },
    { "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand },
    { "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
    { "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
+3 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public class WifiNative {

    public native static boolean startSupplicant();
    
    public native static boolean stopSupplicant();
    public native static boolean killSupplicant();

    public native static boolean connectToSupplicant();

@@ -80,6 +80,8 @@ public class WifiNative {

    public native static boolean disconnectCommand();

    public native static boolean terminateCommand();

    public native static String statusCommand();

    public native static int getRssiCommand();
+94 −23
Original line number Diff line number Diff line
@@ -126,6 +126,18 @@ public class WifiStateMachine extends HierarchicalStateMachine {
     */
    private static final int POLL_RSSI_INTERVAL_MSECS = 3000;

    /**
     * Delay between supplicant restarts upon failure to establish connection
     */
    private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000;

    /**
     * Number of times we attempt to restart supplicant
     */
    private static final int SUPPLICANT_RESTART_TRIES = 5;

    private int mSupplicantRestartCount = 0;

    /**
     * Instance of the bluetooth headset helper. This needs to be created
     * early because there is a delay before it actually 'connects', as
@@ -365,10 +377,11 @@ public class WifiStateMachine extends HierarchicalStateMachine {
    /* Driver loaded */
    private HierarchicalState mDriverLoadedState = new DriverLoadedState();
    /* Driver loaded, waiting for supplicant to start */
    private HierarchicalState mWaitForSupState = new WaitForSupState();

    private HierarchicalState mSupplicantStartingState = new SupplicantStartingState();
    /* Driver loaded and supplicant ready */
    private HierarchicalState mDriverSupReadyState = new DriverSupReadyState();
    private HierarchicalState mSupplicantStartedState = new SupplicantStartedState();
    /* Waiting for supplicant to stop and monitor to exit */
    private HierarchicalState mSupplicantStoppingState = new SupplicantStoppingState();
    /* Driver start issued, waiting for completed event */
    private HierarchicalState mDriverStartingState = new DriverStartingState();
    /* Driver started */
@@ -513,10 +526,10 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                addState(mDriverFailedState, mDriverUnloadedState);
            addState(mDriverLoadingState, mDefaultState);
            addState(mDriverLoadedState, mDefaultState);
                addState(mWaitForSupState, mDriverLoadedState);
            addState(mDriverSupReadyState, mDefaultState);
                addState(mDriverStartingState, mDriverSupReadyState);
                addState(mDriverStartedState, mDriverSupReadyState);
            addState(mSupplicantStartingState, mDefaultState);
            addState(mSupplicantStartedState, mDefaultState);
                addState(mDriverStartingState, mSupplicantStartedState);
                addState(mDriverStartedState, mSupplicantStartedState);
                    addState(mScanModeState, mDriverStartedState);
                    addState(mConnectModeState, mDriverStartedState);
                        addState(mConnectingState, mConnectModeState);
@@ -524,8 +537,9 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                        addState(mDisconnectingState, mConnectModeState);
                        addState(mDisconnectedState, mConnectModeState);
                        addState(mWaitForWpsCompletionState, mConnectModeState);
                addState(mDriverStoppingState, mDriverSupReadyState);
                addState(mDriverStoppedState, mDriverSupReadyState);
                addState(mDriverStoppingState, mSupplicantStartedState);
                addState(mDriverStoppedState, mSupplicantStartedState);
            addState(mSupplicantStoppingState, mDefaultState);
            addState(mSoftApStartedState, mDefaultState);

        setInitialState(mInitialState);
@@ -1742,7 +1756,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                        Log.d(TAG, "Supplicant start successful");
                        mWifiMonitor.startMonitoring();
                        setWifiState(WIFI_STATE_ENABLED);
                        transitionTo(mWaitForSupState);
                        transitionTo(mSupplicantStartingState);
                    } else {
                        Log.e(TAG, "Failed to start supplicant!");
                        sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
@@ -1888,7 +1902,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
    }


    class WaitForSupState extends HierarchicalState {
    class SupplicantStartingState extends HierarchicalState {
        @Override
        public void enter() {
            if (DBG) Log.d(TAG, getName() + "\n");
@@ -1900,6 +1914,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
            switch(message.what) {
                case SUP_CONNECTION_EVENT:
                    Log.d(TAG, "Supplicant connection established");
                    mSupplicantRestartCount = 0;
                    mSupplicantStateTracker.resetSupplicantState();
                    /* Initialize data structures */
                    mLastBssid = null;
@@ -1919,10 +1934,18 @@ public class WifiStateMachine extends HierarchicalStateMachine {
                    transitionTo(mDriverStartedState);
                    break;
                case SUP_DISCONNECTION_EVENT:
                    if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
                        Log.e(TAG, "Failed to setup control channel, restart supplicant");
                    WifiNative.stopSupplicant();
                        WifiNative.killSupplicant();
                        transitionTo(mDriverLoadedState);
                        sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                    } else {
                        mSupplicantRestartCount = 0;
                        Log.e(TAG, "Failed " + mSupplicantRestartCount +
                                " times to start supplicant, unload driver");
                        transitionTo(mDriverLoadedState);
                    sendMessageAtFrontOfQueue(CMD_START_SUPPLICANT);
                        sendMessage(CMD_UNLOAD_DRIVER);
                    }
                    break;
                case CMD_LOAD_DRIVER:
                case CMD_UNLOAD_DRIVER:
@@ -1951,7 +1974,7 @@ public class WifiStateMachine extends HierarchicalStateMachine {
        }
    }

    class DriverSupReadyState extends HierarchicalState {
    class SupplicantStartedState extends HierarchicalState {
        @Override
        public void enter() {
            if (DBG) Log.d(TAG, getName() + "\n");
@@ -1966,23 +1989,26 @@ public class WifiStateMachine extends HierarchicalStateMachine {
            switch(message.what) {
                case CMD_STOP_SUPPLICANT:   /* Supplicant stopped by user */
                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                    Log.d(TAG, "Stop supplicant received");
                    WifiNative.closeSupplicantConnection();
                    WifiNative.stopSupplicant();
                    Log.d(TAG, "send terminate command to supplicant");
                    if (!WifiNative.terminateCommand()) {
                        Log.e(TAG, "Failed to terminate cleanly, issue kill");
                        WifiNative.killSupplicant();
                    }
                    handleNetworkDisconnect();
                    sendSupplicantConnectionChangedBroadcast(false);
                    mSupplicantStateTracker.resetSupplicantState();
                    transitionTo(mDriverLoadedState);
                    transitionTo(mSupplicantStoppingState);
                    break;
                case SUP_DISCONNECTION_EVENT:  /* Supplicant died */
                case SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
                    EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
                    Log.e(TAG, "Supplicant died, restarting");
                    Log.e(TAG, "Connection lost, restart supplicant");
                    WifiNative.killSupplicant();
                    WifiNative.closeSupplicantConnection();
                    handleNetworkDisconnect();
                    sendSupplicantConnectionChangedBroadcast(false);
                    mSupplicantStateTracker.resetSupplicantState();
                    transitionTo(mDriverLoadedState);
                    sendMessageAtFrontOfQueue(CMD_START_SUPPLICANT); /* restart */
                    sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                    break;
                case SCAN_RESULTS_EVENT:
                    setScanResults(WifiNative.scanResultsCommand());
@@ -2058,6 +2084,51 @@ public class WifiStateMachine extends HierarchicalStateMachine {
        }
    }

    class SupplicantStoppingState extends HierarchicalState {
        @Override
        public void enter() {
            if (DBG) Log.d(TAG, getName() + "\n");
            EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
        }
        @Override
        public boolean processMessage(Message message) {
            if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
            switch(message.what) {
                case SUP_CONNECTION_EVENT:
                    Log.e(TAG, "Supplicant connection received while stopping");
                    break;
                case SUP_DISCONNECTION_EVENT:
                    Log.d(TAG, "Supplicant connection lost");
                    WifiNative.closeSupplicantConnection();
                    transitionTo(mDriverLoadedState);
                    break;
                case CMD_LOAD_DRIVER:
                case CMD_UNLOAD_DRIVER:
                case CMD_START_SUPPLICANT:
                case CMD_STOP_SUPPLICANT:
                case CMD_START_AP:
                case CMD_STOP_AP:
                case CMD_START_DRIVER:
                case CMD_STOP_DRIVER:
                case CMD_SET_SCAN_MODE:
                case CMD_SET_SCAN_TYPE:
                case CMD_SET_HIGH_PERF_MODE:
                case CMD_SET_BLUETOOTH_COEXISTENCE:
                case CMD_SET_BLUETOOTH_SCAN_MODE:
                case CMD_SET_COUNTRY_CODE:
                case CMD_SET_FREQUENCY_BAND:
                case CMD_START_PACKET_FILTERING:
                case CMD_STOP_PACKET_FILTERING:
                    deferMessage(message);
                    break;
                default:
                    return NOT_HANDLED;
            }
            EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
            return HANDLED;
        }
    }

    class DriverStartingState extends HierarchicalState {
        @Override
        public void enter() {