FileDocCategorySizeDatePackage
WifiMonitor.javaAPI DocAndroid 5.1 API57165Thu Mar 12 22:22:52 GMT 2015com.android.server.wifi

WifiMonitor

public class WifiMonitor extends Object
Listens for events from the wpa_supplicant server, and passes them on to the {@link StateMachine} for handling. Runs in its own thread.
hide

Fields Summary
private static boolean
DBG
private static final boolean
VDBG
private static final String
TAG
private static final int
CONNECTED
Events we receive from the supplicant daemon
private static final int
DISCONNECTED
private static final int
STATE_CHANGE
private static final int
SCAN_RESULTS
private static final int
LINK_SPEED
private static final int
TERMINATING
private static final int
DRIVER_STATE
private static final int
EAP_FAILURE
private static final int
ASSOC_REJECT
private static final int
SSID_TEMP_DISABLE
private static final int
SSID_REENABLE
private static final int
BSS_ADDED
private static final int
BSS_REMOVED
private static final int
UNKNOWN
private static final String
EVENT_PREFIX_STR
All events coming from the supplicant start with this prefix
private static final int
EVENT_PREFIX_LEN_STR
private static final String
REQUEST_PREFIX_STR
All events coming from the supplicant start with this prefix
private static final int
REQUEST_PREFIX_LEN_STR
private static final String
WPA_EVENT_PREFIX_STR
All WPA events coming from the supplicant start with this prefix
private static final String
PASSWORD_MAY_BE_INCORRECT_STR
private static final String
WPS_SUCCESS_STR
private static final String
WPS_FAIL_STR
private static final String
WPS_FAIL_PATTERN
private static final int
CONFIG_MULTIPLE_PBC_DETECTED
private static final int
CONFIG_AUTH_FAILURE
private static final int
REASON_TKIP_ONLY_PROHIBITED
private static final int
REASON_WEP_PROHIBITED
private static final String
WPS_OVERLAP_STR
private static final String
WPS_TIMEOUT_STR
private static final String
GAS_QUERY_PREFIX_STR
private static final String
GAS_QUERY_START_STR
private static final String
GAS_QUERY_DONE_STR
private static final String
RX_HS20_ANQP_ICON_STR
private static final int
RX_HS20_ANQP_ICON_STR_LEN
private static final String
HS20_PREFIX_STR
private static final String
HS20_SUB_REM_STR
private static final String
HS20_DEAUTH_STR
private static final String
IDENTITY_STR
private static final String
SIM_STR
private static int
eventLogCounter
private static final String
CONNECTED_STR
CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:xx:xx completed
xx:xx:xx:xx:xx:xx is the BSSID of the associated access point
private static final String
DISCONNECTED_STR
CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys
private static final String
STATE_CHANGE_STR
CTRL-EVENT-STATE-CHANGE x
x is the numerical value of the new state.
private static final String
SCAN_RESULTS_STR
CTRL-EVENT-SCAN-RESULTS ready
private static final String
LINK_SPEED_STR
CTRL-EVENT-LINK-SPEED x Mb/s
{@code x} is the link speed in Mb/sec.
private static final String
TERMINATING_STR
CTRL-EVENT-TERMINATING - signal x
x is the signal that caused termination.
private static final String
DRIVER_STATE_STR
CTRL-EVENT-DRIVER-STATE state
state can be HANGED
private static final String
EAP_FAILURE_STR
CTRL-EVENT-EAP-FAILURE EAP authentication failed
private static final String
EAP_AUTH_FAILURE_STR
This indicates an authentication failure on EAP FAILURE event
private static final String
ASSOC_REJECT_STR
This indicates an assoc reject event
private static final String
TEMP_DISABLED_STR
This indicates auth or association failure bad enough so as network got disabled - WPA_PSK auth failure suspecting shared key mismatch - failed multiple Associations
private static final String
REENABLED_STR
This indicates a previously disabled SSID was reenabled by supplicant
private static final String
BSS_ADDED_STR
This indicates supplicant found a given BSS
private static final String
BSS_REMOVED_STR
This indicates supplicant removed a given BSS
private static Pattern
mConnectedEventPattern
Regex pattern for extracting an Ethernet-style MAC address from a string. Matches a strings like the following:
CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]
private static Pattern
mDisconnectedEventPattern
Regex pattern for extracting an Ethernet-style MAC address from a string. Matches a strings like the following:
CTRL-EVENT-DISCONNECTED - bssid=ac:22:0b:24:70:74 reason=3 locally_generated=1
private static Pattern
mAssocRejectEventPattern
Regex pattern for extracting an Ethernet-style MAC address from a string. Matches a strings like the following:
CTRL-EVENT-ASSOC-REJECT - bssid=ac:22:0b:24:70:74 status_code=1
private static final String
TARGET_BSSID_STR
Regex pattern for extracting an Ethernet-style MAC address from a string. Matches a strings like the following:
IFNAME=wlan0 Trying to associate with 6c:f3:7f:ae:87:71
private static Pattern
mTargetBSSIDPattern
private static final String
ASSOCIATED_WITH_STR
Regex pattern for extracting an Ethernet-style MAC address from a string. Matches a strings like the following:
IFNAME=wlan0 Associated with 6c:f3:7f:ae:87:71
private static Pattern
mAssociatedPattern
private static Pattern
mRequestGsmAuthPattern
Regex pattern for extracting SSIDs from request identity string. Matches a strings like the following:
CTRL-REQ-SIM-:GSM-AUTH::[:] needed for SSID 
This pattern should find
0 - id
1 - Rand1
2 - Rand2
3 - Rand3
4 - SSID
private static Pattern
mRequestIdentityPattern
Regex pattern for extracting SSIDs from request identity string. Matches a strings like the following:
CTRL-REQ-IDENTITY-xx:Identity needed for SSID XXXX
private static final String
P2P_EVENT_PREFIX_STR
P2P events
private static final String
P2P_DEVICE_FOUND_STR
private static final String
P2P_DEVICE_LOST_STR
private static final String
P2P_FIND_STOPPED_STR
private static final String
P2P_GO_NEG_REQUEST_STR
private static final String
P2P_GO_NEG_SUCCESS_STR
private static final String
P2P_GO_NEG_FAILURE_STR
private static final String
P2P_GROUP_FORMATION_SUCCESS_STR
private static final String
P2P_GROUP_FORMATION_FAILURE_STR
private static final String
P2P_GROUP_STARTED_STR
private static final String
P2P_GROUP_REMOVED_STR
private static final String
P2P_INVITATION_RECEIVED_STR
private static final String
P2P_INVITATION_RESULT_STR
private static final String
P2P_PROV_DISC_PBC_REQ_STR
private static final String
P2P_PROV_DISC_PBC_RSP_STR
private static final String
P2P_PROV_DISC_ENTER_PIN_STR
private static final String
P2P_PROV_DISC_SHOW_PIN_STR
private static final String
P2P_PROV_DISC_FAILURE_STR
private static final String
P2P_SERV_DISC_RESP_STR
private static final String
HOST_AP_EVENT_PREFIX_STR
private static final String
AP_STA_CONNECTED_STR
private static final String
AP_STA_DISCONNECTED_STR
private static final int
BASE
public static final int
SUP_CONNECTION_EVENT
public static final int
SUP_DISCONNECTION_EVENT
public static final int
NETWORK_CONNECTION_EVENT
public static final int
NETWORK_DISCONNECTION_EVENT
public static final int
SCAN_RESULTS_EVENT
public static final int
SUPPLICANT_STATE_CHANGE_EVENT
public static final int
AUTHENTICATION_FAILURE_EVENT
public static final int
WPS_SUCCESS_EVENT
public static final int
WPS_FAIL_EVENT
public static final int
WPS_OVERLAP_EVENT
public static final int
WPS_TIMEOUT_EVENT
public static final int
DRIVER_HUNG_EVENT
public static final int
SSID_TEMP_DISABLED
public static final int
SSID_REENABLED
public static final int
SUP_REQUEST_IDENTITY
public static final int
SUP_REQUEST_SIM_AUTH
public static final int
P2P_DEVICE_FOUND_EVENT
public static final int
P2P_DEVICE_LOST_EVENT
public static final int
P2P_GO_NEGOTIATION_REQUEST_EVENT
public static final int
P2P_GO_NEGOTIATION_SUCCESS_EVENT
public static final int
P2P_GO_NEGOTIATION_FAILURE_EVENT
public static final int
P2P_GROUP_FORMATION_SUCCESS_EVENT
public static final int
P2P_GROUP_FORMATION_FAILURE_EVENT
public static final int
P2P_GROUP_STARTED_EVENT
public static final int
P2P_GROUP_REMOVED_EVENT
public static final int
P2P_INVITATION_RECEIVED_EVENT
public static final int
P2P_INVITATION_RESULT_EVENT
public static final int
P2P_PROV_DISC_PBC_REQ_EVENT
public static final int
P2P_PROV_DISC_PBC_RSP_EVENT
public static final int
P2P_PROV_DISC_ENTER_PIN_EVENT
public static final int
P2P_PROV_DISC_SHOW_PIN_EVENT
public static final int
P2P_FIND_STOPPED_EVENT
public static final int
P2P_SERV_DISC_RESP_EVENT
public static final int
P2P_PROV_DISC_FAILURE_EVENT
public static final int
AP_STA_DISCONNECTED_EVENT
public static final int
AP_STA_CONNECTED_EVENT
public static final int
ASSOCIATION_REJECTION_EVENT
public static final int
GAS_QUERY_START_EVENT
public static final int
GAS_QUERY_DONE_EVENT
public static final int
RX_HS20_ANQP_ICON_EVENT
public static final int
HS20_REMEDIATION_EVENT
public static final int
HS20_DEAUTH_EVENT
private static final String
WPA_RECV_ERROR_STR
This indicates a read error on the monitor socket conenction
private static final int
MAX_RECV_ERRORS
Max errors before we close supplicant connection
private final String
mInterfaceName
private final WifiNative
mWifiNative
private final com.android.internal.util.StateMachine
mStateMachine
private com.android.internal.util.StateMachine
mStateMachine2
private boolean
mMonitoring
private static int
sRecvErrors
Constructors Summary
public WifiMonitor(com.android.internal.util.StateMachine stateMachine, WifiNative wifiNative)


         
        if (DBG) Log.d(TAG, "Creating WifiMonitor");
        mWifiNative = wifiNative;
        mInterfaceName = wifiNative.mInterfaceName;
        mStateMachine = stateMachine;
        mStateMachine2 = null;
        mMonitoring = false;

        WifiMonitorSingleton.sInstance.registerInterfaceMonitor(mInterfaceName, this);
    
Methods Summary
private booleandispatchEvent(java.lang.String eventStr, java.lang.String iface)


        if (DBG) {
            // Dont log CTRL-EVENT-BSS-ADDED which are too verbose and not handled
            if (eventStr != null && !eventStr.contains("CTRL-EVENT-BSS-ADDED")) {
                logDbg("WifiMonitor:" + iface + " cnt=" + Integer.toString(eventLogCounter)
                        + " dispatchEvent: " + eventStr);
            }
        }

        if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
            if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
                    0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
               mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT, eventLogCounter);
            } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
                mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
            } else if (eventStr.startsWith(WPS_FAIL_STR)) {
                handleWpsFailEvent(eventStr);
            } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
                mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
            } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
                mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);
            } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
                handleP2pEvents(eventStr);
            } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
                handleHostApEvents(eventStr);
            } else if (eventStr.startsWith(GAS_QUERY_PREFIX_STR)) {
                handleGasQueryEvents(eventStr);
            } else if (eventStr.startsWith(RX_HS20_ANQP_ICON_STR)) {
                if (mStateMachine2 != null)
                    mStateMachine2.sendMessage(RX_HS20_ANQP_ICON_EVENT,
                            eventStr.substring(RX_HS20_ANQP_ICON_STR_LEN + 1));
            } else if (eventStr.startsWith(HS20_PREFIX_STR)) {
                handleHs20Events(eventStr);
            } else if (eventStr.startsWith(REQUEST_PREFIX_STR)) {
                handleRequests(eventStr);
            } else if (eventStr.startsWith(TARGET_BSSID_STR)) {
                handleTargetBSSIDEvent(eventStr);
            } else if (eventStr.startsWith(ASSOCIATED_WITH_STR)) {
                handleAssociatedBSSIDEvent(eventStr);
            } else {
                if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
            }
            eventLogCounter++;
            return false;
        }

        String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
        int nameEnd = eventName.indexOf(' ");
        if (nameEnd != -1)
            eventName = eventName.substring(0, nameEnd);
        if (eventName.length() == 0) {
            if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name");
            eventLogCounter++;
            return false;
        }
        /*
        * Map event name into event enum
        */
        int event;
        if (eventName.equals(CONNECTED_STR))
            event = CONNECTED;
        else if (eventName.equals(DISCONNECTED_STR))
            event = DISCONNECTED;
        else if (eventName.equals(STATE_CHANGE_STR))
            event = STATE_CHANGE;
        else if (eventName.equals(SCAN_RESULTS_STR))
            event = SCAN_RESULTS;
        else if (eventName.equals(LINK_SPEED_STR))
            event = LINK_SPEED;
        else if (eventName.equals(TERMINATING_STR))
            event = TERMINATING;
        else if (eventName.equals(DRIVER_STATE_STR))
            event = DRIVER_STATE;
        else if (eventName.equals(EAP_FAILURE_STR))
            event = EAP_FAILURE;
        else if (eventName.equals(ASSOC_REJECT_STR))
            event = ASSOC_REJECT;
        else if (eventName.equals(TEMP_DISABLED_STR)) {
            event = SSID_TEMP_DISABLE;
        } else if (eventName.equals(REENABLED_STR)) {
            event = SSID_REENABLE;
        } else if (eventName.equals(BSS_ADDED_STR)) {
            event = BSS_ADDED;
        } else if (eventName.equals(BSS_REMOVED_STR)) {
            event = BSS_REMOVED;
        }
        else
            event = UNKNOWN;

        String eventData = eventStr;
        if (event == DRIVER_STATE || event == LINK_SPEED)
            eventData = eventData.split(" ")[1];
        else if (event == STATE_CHANGE || event == EAP_FAILURE) {
            int ind = eventStr.indexOf(" ");
            if (ind != -1) {
                eventData = eventStr.substring(ind + 1);
            }
        } else {
            int ind = eventStr.indexOf(" - ");
            if (ind != -1) {
                eventData = eventStr.substring(ind + 3);
            }
        }

        if ((event == SSID_TEMP_DISABLE)||(event == SSID_REENABLE)) {
            String substr = null;
            int netId = -1;
            int ind = eventStr.indexOf(" ");
            if (ind != -1) {
                substr = eventStr.substring(ind + 1);
            }
            if (substr != null) {
                String status[] = substr.split(" ");
                for (String key : status) {
                    if (key.regionMatches(0, "id=", 0, 3)) {
                        int idx = 3;
                        netId = 0;
                        while (idx < key.length()) {
                            char c = key.charAt(idx);
                            if ((c >= 0x30) && (c <= 0x39)) {
                                netId *= 10;
                                netId += c - 0x30;
                                idx++;
                            } else {
                                break;
                            }
                        }
                    }
                }
            }
            mStateMachine.sendMessage((event == SSID_TEMP_DISABLE)?
                    SSID_TEMP_DISABLED:SSID_REENABLED, netId, 0, substr);
        } else if (event == STATE_CHANGE) {
            handleSupplicantStateChange(eventData);
        } else if (event == DRIVER_STATE) {
            handleDriverEvent(eventData);
        } else if (event == TERMINATING) {
            /**
             * Close the supplicant connection if we see
             * too many recv errors
             */
            if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
                if (++sRecvErrors > MAX_RECV_ERRORS) {
                    if (DBG) {
                        Log.d(TAG, "too many recv errors, closing connection");
                    }
                } else {
                    eventLogCounter++;
                    return false;
                }
            }

            // Notify and exit
            mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT, eventLogCounter);
            return true;
        } else if (event == EAP_FAILURE) {
            if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
                logDbg("WifiMonitor send auth failure (EAP_AUTH_FAILURE) ");
                mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT, eventLogCounter);
            }
        } else if (event == ASSOC_REJECT) {
            Matcher match = mAssocRejectEventPattern.matcher(eventData);
            String BSSID = "";
            int status = -1;
            if (!match.find()) {
                if (DBG) Log.d(TAG, "Assoc Reject: Could not parse assoc reject string");
            } else {
                BSSID = match.group(1);
                try {
                    status = Integer.parseInt(match.group(2));
                } catch (NumberFormatException e) {
                    status = -1;
                }
            }
            mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT, eventLogCounter, status, BSSID);
        } else if (event == BSS_ADDED && !VDBG) {
            // Ignore that event - it is not handled, and dont log it as it is too verbose
        } else if (event == BSS_REMOVED && !VDBG) {
            // Ignore that event - it is not handled, and dont log it as it is too verbose
        }  else {
                handleEvent(event, eventData);
        }
        sRecvErrors = 0;
        eventLogCounter++;
        return false;
    
voidenableVerboseLogging(int verbose)

        if (verbose > 0) {
            DBG = true;
        } else {
            DBG = false;
        }
    
private voidhandleAssociatedBSSIDEvent(java.lang.String eventStr)

        String BSSID = null;
        Matcher match = mAssociatedPattern.matcher(eventStr);
        if (match.find()) {
            BSSID = match.group(1);
        }
        mStateMachine.sendMessage(WifiStateMachine.CMD_ASSOCIATED_BSSID, eventLogCounter, 0, BSSID);
    
private voidhandleDriverEvent(java.lang.String state)

        if (state == null) {
            return;
        }
        if (state.equals("HANGED")) {
            mStateMachine.sendMessage(DRIVER_HUNG_EVENT);
        }
    
voidhandleEvent(int event, java.lang.String remainder)
Handle all supplicant events except STATE-CHANGE

param
event the event type
param
remainder the rest of the string following the event name and " — "

        if (DBG) {
            logDbg("handleEvent " + Integer.toString(event) + "  " + remainder);
        }
        switch (event) {
            case DISCONNECTED:
                handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);
                break;

            case CONNECTED:
                handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);
                break;

            case SCAN_RESULTS:
                mStateMachine.sendMessage(SCAN_RESULTS_EVENT);
                break;

            case UNKNOWN:
                if (DBG) {
                    logDbg("handleEvent unknown: " + Integer.toString(event) + "  " + remainder);
                }
                break;
            default:
                break;
        }
    
private voidhandleGasQueryEvents(java.lang.String dataString)
Handle ANQP events

        // hs20
        if (mStateMachine2 == null) return;
        if (dataString.startsWith(GAS_QUERY_START_STR)) {
            mStateMachine2.sendMessage(GAS_QUERY_START_EVENT);
        } else if (dataString.startsWith(GAS_QUERY_DONE_STR)) {
            String[] dataTokens = dataString.split(" ");
            String bssid = null;
            int success = 0;
            for (String token : dataTokens) {
                String[] nameValue = token.split("=");
                if (nameValue.length != 2) {
                    continue;
                }
                if (nameValue[0].equals("addr")) {
                    bssid = nameValue[1];
                    continue;
                }
                if (nameValue[0].equals("result"))  {
                    success = nameValue[1].equals("SUCCESS") ? 1 : 0;
                    continue;
                }
            }
            mStateMachine2.sendMessage(GAS_QUERY_DONE_EVENT, success, 0, bssid);
        } else {
            if (DBG) Log.d(TAG, "Unknown GAS query event: " + dataString);
        }
    
private voidhandleHostApEvents(java.lang.String dataString)
Handle hostap events

        String[] tokens = dataString.split(" ");
        /* AP-STA-CONNECTED 42:fc:89:a8:96:09 p2p_dev_addr=02:90:4c:a0:92:54 */
        if (tokens[0].equals(AP_STA_CONNECTED_STR)) {
            mStateMachine.sendMessage(AP_STA_CONNECTED_EVENT, new WifiP2pDevice(dataString));
            /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 p2p_dev_addr=02:90:4c:a0:92:54 */
        } else if (tokens[0].equals(AP_STA_DISCONNECTED_STR)) {
            mStateMachine.sendMessage(AP_STA_DISCONNECTED_EVENT, new WifiP2pDevice(dataString));
        }
    
private voidhandleHs20Events(java.lang.String dataString)
Handle HS20 events

        if (mStateMachine2 == null) return;
        if (dataString.startsWith(HS20_SUB_REM_STR)) {
            // format: HS20-SUBSCRIPTION-REMEDIATION osu_method, url
            String[] dataTokens = dataString.split(" ");
            int method = -1;
            String url = null;
            if (dataTokens.length >= 3) {
                method = Integer.parseInt(dataTokens[1]);
                url = dataTokens[2];
            }
            mStateMachine2.sendMessage(HS20_REMEDIATION_EVENT, method, 0, url);
        } else if (dataString.startsWith(HS20_DEAUTH_STR)) {
            // format: HS20-DEAUTH-IMMINENT-NOTICE code, delay, url
            int code = -1;
            int delay = -1;
            String url = null;
            String[] dataTokens = dataString.split(" ");
            if (dataTokens.length >= 4) {
                code = Integer.parseInt(dataTokens[1]);
                delay = Integer.parseInt(dataTokens[2]);
                url = dataTokens[3];
            }
            mStateMachine2.sendMessage(HS20_DEAUTH_EVENT, code, delay, url);
        } else {
            if (DBG) Log.d(TAG, "Unknown HS20 event: " + dataString);
        }
    
private voidhandleNetworkStateChange(NetworkInfo.DetailedState newState, java.lang.String data)

        String BSSID = null;
        int networkId = -1;
        int reason = 0;
        int ind = -1;
        int local = 0;
        Matcher match;
        if (newState == NetworkInfo.DetailedState.CONNECTED) {
            match = mConnectedEventPattern.matcher(data);
            if (!match.find()) {
               if (DBG) Log.d(TAG, "handleNetworkStateChange: Couldnt find BSSID in event string");
            } else {
                BSSID = match.group(1);
                try {
                    networkId = Integer.parseInt(match.group(2));
                } catch (NumberFormatException e) {
                    networkId = -1;
                }
            }
            notifyNetworkStateChange(newState, BSSID, networkId, reason);
        } else if (newState == NetworkInfo.DetailedState.DISCONNECTED) {
            match = mDisconnectedEventPattern.matcher(data);
            if (!match.find()) {
               if (DBG) Log.d(TAG, "handleNetworkStateChange: Could not parse disconnect string");
            } else {
                BSSID = match.group(1);
                try {
                    reason = Integer.parseInt(match.group(2));
                } catch (NumberFormatException e) {
                    reason = -1;
                }
                try {
                    local = Integer.parseInt(match.group(3));
                } catch (NumberFormatException e) {
                    local = -1;
                }
            }
            notifyNetworkStateChange(newState, BSSID, local, reason);
        }
    
private voidhandleP2pEvents(java.lang.String dataString)
Handle p2p events

        if (dataString.startsWith(P2P_DEVICE_FOUND_STR)) {
            mStateMachine.sendMessage(P2P_DEVICE_FOUND_EVENT, new WifiP2pDevice(dataString));
        } else if (dataString.startsWith(P2P_DEVICE_LOST_STR)) {
            mStateMachine.sendMessage(P2P_DEVICE_LOST_EVENT, new WifiP2pDevice(dataString));
        } else if (dataString.startsWith(P2P_FIND_STOPPED_STR)) {
            mStateMachine.sendMessage(P2P_FIND_STOPPED_EVENT);
        } else if (dataString.startsWith(P2P_GO_NEG_REQUEST_STR)) {
            mStateMachine.sendMessage(P2P_GO_NEGOTIATION_REQUEST_EVENT,
                    new WifiP2pConfig(dataString));
        } else if (dataString.startsWith(P2P_GO_NEG_SUCCESS_STR)) {
            mStateMachine.sendMessage(P2P_GO_NEGOTIATION_SUCCESS_EVENT);
        } else if (dataString.startsWith(P2P_GO_NEG_FAILURE_STR)) {
            mStateMachine.sendMessage(P2P_GO_NEGOTIATION_FAILURE_EVENT, p2pError(dataString));
        } else if (dataString.startsWith(P2P_GROUP_FORMATION_SUCCESS_STR)) {
            mStateMachine.sendMessage(P2P_GROUP_FORMATION_SUCCESS_EVENT);
        } else if (dataString.startsWith(P2P_GROUP_FORMATION_FAILURE_STR)) {
            mStateMachine.sendMessage(P2P_GROUP_FORMATION_FAILURE_EVENT, p2pError(dataString));
        } else if (dataString.startsWith(P2P_GROUP_STARTED_STR)) {
            mStateMachine.sendMessage(P2P_GROUP_STARTED_EVENT, new WifiP2pGroup(dataString));
        } else if (dataString.startsWith(P2P_GROUP_REMOVED_STR)) {
            mStateMachine.sendMessage(P2P_GROUP_REMOVED_EVENT, new WifiP2pGroup(dataString));
        } else if (dataString.startsWith(P2P_INVITATION_RECEIVED_STR)) {
            mStateMachine.sendMessage(P2P_INVITATION_RECEIVED_EVENT,
                    new WifiP2pGroup(dataString));
        } else if (dataString.startsWith(P2P_INVITATION_RESULT_STR)) {
            mStateMachine.sendMessage(P2P_INVITATION_RESULT_EVENT, p2pError(dataString));
        } else if (dataString.startsWith(P2P_PROV_DISC_PBC_REQ_STR)) {
            mStateMachine.sendMessage(P2P_PROV_DISC_PBC_REQ_EVENT,
                    new WifiP2pProvDiscEvent(dataString));
        } else if (dataString.startsWith(P2P_PROV_DISC_PBC_RSP_STR)) {
            mStateMachine.sendMessage(P2P_PROV_DISC_PBC_RSP_EVENT,
                    new WifiP2pProvDiscEvent(dataString));
        } else if (dataString.startsWith(P2P_PROV_DISC_ENTER_PIN_STR)) {
            mStateMachine.sendMessage(P2P_PROV_DISC_ENTER_PIN_EVENT,
                    new WifiP2pProvDiscEvent(dataString));
        } else if (dataString.startsWith(P2P_PROV_DISC_SHOW_PIN_STR)) {
            mStateMachine.sendMessage(P2P_PROV_DISC_SHOW_PIN_EVENT,
                    new WifiP2pProvDiscEvent(dataString));
        } else if (dataString.startsWith(P2P_PROV_DISC_FAILURE_STR)) {
            mStateMachine.sendMessage(P2P_PROV_DISC_FAILURE_EVENT);
        } else if (dataString.startsWith(P2P_SERV_DISC_RESP_STR)) {
            List<WifiP2pServiceResponse> list = WifiP2pServiceResponse.newInstance(dataString);
            if (list != null) {
                mStateMachine.sendMessage(P2P_SERV_DISC_RESP_EVENT, list);
            } else {
                Log.e(TAG, "Null service resp " + dataString);
            }
        }
    
private voidhandleRequests(java.lang.String dataString)
Handle Supplicant Requests

        String SSID = null;
        int reason = -2;
        String requestName = dataString.substring(REQUEST_PREFIX_LEN_STR);
        if (TextUtils.isEmpty(requestName)) {
            return;
        }
        if (requestName.startsWith(IDENTITY_STR)) {
            Matcher match = mRequestIdentityPattern.matcher(requestName);
            if (match.find()) {
                SSID = match.group(2);
                try {
                    reason = Integer.parseInt(match.group(1));
                } catch (NumberFormatException e) {
                    reason = -1;
                }
            } else {
                Log.e(TAG, "didn't find SSID " + requestName);
            }
            mStateMachine.sendMessage(SUP_REQUEST_IDENTITY, eventLogCounter, reason, SSID);
        } if (requestName.startsWith(SIM_STR)) {
            Matcher match = mRequestGsmAuthPattern.matcher(requestName);
            if (match.find()) {
                WifiStateMachine.SimAuthRequestData data =
                        new WifiStateMachine.SimAuthRequestData();
                data.networkId = Integer.parseInt(match.group(1));
                data.protocol = WifiEnterpriseConfig.Eap.SIM;
                data.ssid = match.group(4);
                data.challenges = match.group(2).split(":");
                mStateMachine.sendMessage(SUP_REQUEST_SIM_AUTH, data);
            } else {
                Log.e(TAG, "couldn't parse SIM auth request - " + requestName);
            }

        } else {
            if (DBG) Log.w(TAG, "couldn't identify request type - " + dataString);
        }
    
private voidhandleSupplicantStateChange(java.lang.String dataString)
Handle the supplicant STATE-CHANGE event

param
dataString New supplicant state string in the format: id=network-id state=new-state

        WifiSsid wifiSsid = null;
        int index = dataString.lastIndexOf("SSID=");
        if (index != -1) {
            wifiSsid = WifiSsid.createFromAsciiEncoded(
                    dataString.substring(index + 5));
        }
        String[] dataTokens = dataString.split(" ");

        String BSSID = null;
        int networkId = -1;
        int newState  = -1;
        for (String token : dataTokens) {
            String[] nameValue = token.split("=");
            if (nameValue.length != 2) {
                continue;
            }

            if (nameValue[0].equals("BSSID")) {
                BSSID = nameValue[1];
                continue;
            }

            int value;
            try {
                value = Integer.parseInt(nameValue[1]);
            } catch (NumberFormatException e) {
                continue;
            }

            if (nameValue[0].equals("id")) {
                networkId = value;
            } else if (nameValue[0].equals("state")) {
                newState = value;
            }
        }

        if (newState == -1) return;

        SupplicantState newSupplicantState = SupplicantState.INVALID;
        for (SupplicantState state : SupplicantState.values()) {
            if (state.ordinal() == newState) {
                newSupplicantState = state;
                break;
            }
        }
        if (newSupplicantState == SupplicantState.INVALID) {
            Log.w(TAG, "Invalid supplicant state: " + newState);
        }
        notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState);
    
private voidhandleTargetBSSIDEvent(java.lang.String eventStr)

        String BSSID = null;
        Matcher match = mTargetBSSIDPattern.matcher(eventStr);
        if (match.find()) {
            BSSID = match.group(1);
        }
        mStateMachine.sendMessage(WifiStateMachine.CMD_TARGET_BSSID, eventLogCounter, 0, BSSID);
    
private voidhandleWpsFailEvent(java.lang.String dataString)

        final Pattern p = Pattern.compile(WPS_FAIL_PATTERN);
        Matcher match = p.matcher(dataString);
        int reason = 0;
        if (match.find()) {
            String cfgErrStr = match.group(1);
            String reasonStr = match.group(2);

            if (reasonStr != null) {
                int reasonInt = Integer.parseInt(reasonStr);
                switch(reasonInt) {
                    case REASON_TKIP_ONLY_PROHIBITED:
                        mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
                                WifiManager.WPS_TKIP_ONLY_PROHIBITED, 0));
                        return;
                    case REASON_WEP_PROHIBITED:
                        mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
                                WifiManager.WPS_WEP_PROHIBITED, 0));
                        return;
                    default:
                        reason = reasonInt;
                        break;
                }
            }
            if (cfgErrStr != null) {
                int cfgErrInt = Integer.parseInt(cfgErrStr);
                switch(cfgErrInt) {
                    case CONFIG_AUTH_FAILURE:
                        mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
                                WifiManager.WPS_AUTH_FAILURE, 0));
                        return;
                    case CONFIG_MULTIPLE_PBC_DETECTED:
                        mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
                                WifiManager.WPS_OVERLAP_ERROR, 0));
                        return;
                    default:
                        if (reason == 0) reason = cfgErrInt;
                        break;
                }
            }
        }
        //For all other errors, return a generic internal error
        mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
                WifiManager.ERROR, reason));
    
public voidkillSupplicant(boolean p2pSupported)

        WifiMonitorSingleton.sInstance.killSupplicant(p2pSupported);
    
private voidlogDbg(java.lang.String debug)

        Log.e(TAG, debug/*+ " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
                +" - "+ Thread.currentThread().getStackTrace()[3].getMethodName()
                +" - "+ Thread.currentThread().getStackTrace()[4].getMethodName()
                +" - "+ Thread.currentThread().getStackTrace()[5].getMethodName()*/);
    
voidnotifyNetworkStateChange(NetworkInfo.DetailedState newState, java.lang.String BSSID, int netId, int reason)
Send the state machine a notification that the state of Wifi connectivity has changed.

param
newState the new network state
param
BSSID when the new state is {@link NetworkInfo.DetailedState#CONNECTED}, this is the MAC address of the access point. Otherwise, it is {@code null}.
param
netId the configured network on which the state change occurred

        if (newState == NetworkInfo.DetailedState.CONNECTED) {
            Message m = mStateMachine.obtainMessage(NETWORK_CONNECTION_EVENT,
                    netId, reason, BSSID);
            mStateMachine.sendMessage(m);
        } else {

            Message m = mStateMachine.obtainMessage(NETWORK_DISCONNECTION_EVENT,
                    netId, reason, BSSID);
            if (DBG) logDbg("WifiMonitor notify network disconnect: "
                    + BSSID
                    + " reason=" + Integer.toString(reason));
            mStateMachine.sendMessage(m);
        }
    
voidnotifySupplicantStateChange(int networkId, android.net.wifi.WifiSsid wifiSsid, java.lang.String BSSID, android.net.wifi.SupplicantState newState)
Send the state machine a notification that the state of the supplicant has changed.

param
networkId the configured network on which the state change occurred
param
wifiSsid network name
param
BSSID network address
param
newState the new {@code SupplicantState}

        mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
                eventLogCounter, 0,
                new StateChangeResult(networkId, wifiSsid, BSSID, newState)));
    
private com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatusp2pError(java.lang.String dataString)

        P2pStatus err = P2pStatus.UNKNOWN;
        String[] tokens = dataString.split(" ");
        if (tokens.length < 2) return err;
        String[] nameValue = tokens[1].split("=");
        if (nameValue.length != 2) return err;

        /* Handle the special case of reason=FREQ+CONFLICT */
        if (nameValue[1].equals("FREQ_CONFLICT")) {
            return P2pStatus.NO_COMMON_CHANNEL;
        }
        try {
            err = P2pStatus.valueOf(Integer.parseInt(nameValue[1]));
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return err;
    
public voidsetStateMachine2(com.android.internal.util.StateMachine stateMachine)

        mStateMachine2 = stateMachine;
    
public voidstartMonitoring()

        WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);
    
public voidstopMonitoring()

        WifiMonitorSingleton.sInstance.stopMonitoring(mInterfaceName);
    
public voidstopSupplicant()

        WifiMonitorSingleton.sInstance.stopSupplicant();