搜索
 找回密码
 立即注册

简单一步 , 微信登陆

Android wifi探究二:java层的wifi框架(1)

作者:liuwei | 时间:2016-10-13 12:03:37 | 阅读:4737| 只看该作者
从wpa_supplicant接收事件-WifiMonitor
WifiStateMachine的构造函数中创建了一个WifiMonitor的实例:
    public WifiStateMachine(Context context, String wlanInterface,                            WifiTrafficPoller trafficPoller) {        super("WifiStateMachine");        mContext = context;        mSetCountryCode = Settings.Global.getString(                mContext.getContentResolver(), Settings.Global.WIFI_COUNTRY_CODE);        mInterfaceName = wlanInterface;        mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(                BatteryStats.SERVICE_NAME));        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);        mNwService = INetworkManagementService.Stub.asInterface(b);        mP2pSupported = mContext.getPackageManager().hasSystemFeature(                PackageManager.FEATURE_WIFI_DIRECT);        mWifiNative = new WifiNative(mInterfaceName);        mWifiConfigStore = new WifiConfigStore(context,this,  mWifiNative);        mWifiAutoJoinController = new WifiAutoJoinController(context, this,                mWifiConfigStore, mWifiConnecti**tatistics, mWifiNative);        mWifiMonitor = new WifiMonitor(this, mWifiNative);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
然后在InitialState的processMessage中调用mWifiMonitor.startMonitoring();启动**。
       @Override        public boolean processMessage(Message message) {            logStateAndMessage(message, getClass().getSimpleName());            switch (message.what) {                case CMD_START_SUPPLICANT:                     ...                    if (mWifiNative.loadDriver()) {                        try {                            mNwService.wifiFirmwareReload(mInterfaceName, "STA");                        } catch (Exception e) {                            loge("Failed to reload STA firmware " + e);                            // Continue                        }                       ...                        if (mWifiNative.startSupplicant(mP2pSupported)) {                            setWifiState(WIFI_STATE_ENABLING);                            // MStar Android Patch Begin                            mUnwantedNetwork = false;                            // MStar Android Patch End                            if (DBG) log("Supplicant start successful");                            mWifiMonitor.startMonitoring();                            transitionTo(mSupplicantStartingState);                        } else {                            loge("Failed to start supplicant!");                        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
startMonitoring方法定义如下:
    public void startMonitoring() {        WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);    }
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
调用它内部类WifiMonitorSingleton中的startMonitoring做进一步处理:
public synchronized void startMonitoring(String iface) {            WifiMonitor m = mIfaceMap.get(iface);            if (m == null) {                Log.e(TAG, "startMonitor called with unknown iface=" + iface);                return;            }            Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);            if (mConnected) {                m.mMonitoring = true;                m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);            } else {                if (DBG) Log.d(TAG, "connecting to supplicant");                int connectTries = 0;                while (true) {                    if (false == m.mPlugFlag) {                        m.mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);                        Log.e(TAG, "startMonitoring(" + iface + ") failed! Wifi device unplug!");                        break;                    }                    if (mWifiNative.connectToSupplicant()) {                        m.mMonitoring = true;                        m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);                        mConnected = true;                        new MonitorThread(mWifiNative, this).start();                        break;                    }                    if (connectTries++ < 5) {                        try {                            Thread.sleep(1000);                        } catch (InterruptedException ignore) {                        }                    } else {                        m.mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);                        Log.e(TAG, "startMonitoring(" + iface + ") failed!");                        break;                    }                }            }        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
1.首先要判断是够和wpa_supplicant建立连接,如果建立连接了,就一个wifi状态机发送一个SUP_CONNECTION_EVENT消息。如果没有建立连接就尝试建立连接。
2.使用mWifiNative.connectToSupplicant()和wpa_supplicant建立连接。
3.创建MonitorThread**线程。
这个线程工作非常简单,定义如下:
private static class MonitorThread extends Thread {        private final WifiNative mWifiNative;        private final WifiMonitorSingleton mWifiMonitorSingleton;        private final LocalLog mLocalLog = WifiNative.getLocalLog();        public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {            super("WifiMonitor");            mWifiNative = wifiNative;            mWifiMonitorSingleton = wifiMonitorSingleton;        }        public void run() {            if (DBG) {                Log.d(TAG, "MonitorThread start with mConnected=" +                     mWifiMonitorSingleton.mConnected);            }            //noinspection InfiniteLoopStatement            for (;;) {                if (!mWifiMonitorSingleton.mConnected) {                    if (DBG) Log.d(TAG, "MonitorThread exit because mConnected is false");                    break;                }                String eventStr = mWifiNative.waitForEvent();                // Skip logging the common but mostly uninteresting events                if (eventStr.indexOf(BSS_ADDED_STR) == -1                        && eventStr.indexOf(BSS_REMOVED_STR) == -1) {                    if (DBG) Log.d(TAG, "Event [" + eventStr + "]");                    mLocalLog.log("Event [" + eventStr + "]");                }                if (mWifiMonitorSingleton.dispatchEvent(eventStr)) {                    if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");                    break;                }            }        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
1.使用mWifiNative.waitForEvent();**wpa_supplicant发送上来的事件。
2.使用mWifiMonitorSingleton.dispatchEvent(eventStr)分发事件。
时间分发过程如下:
        private synchronized boolean dispatchEvent(String eventStr) {            String iface;            // IFNAME=wlan0 ANQP-QUERY-DONE addr=18:cf:5e:26:a4:88 result=SUCCESS            if (eventStr.startsWith("IFNAME=")) {                int space = eventStr.indexOf(' ');                if (space != -1) {                    iface = eventStr.substring(7, space);                    if (!mIfaceMap.containsKey(iface) && iface.startsWith("p2p-")) {                        // p2p interfaces are created dynamically, but we have                        // only one P2p state machine monitoring all of them; look                        // for it explicitly, and send messages there ..                        iface = "p2p0";                    }                    eventStr = eventStr.substring(space + 1);                } else {                    // No point dispatching this event to any interface, the dispatched                    // event string will begin with "IFNAME=" which dispatchEvent can't really                    // do anything about.                    Log.e(TAG, "Dropping malformed event (unparsable iface): " + eventStr);                    return false;                }            } else {                // events without prefix belong to p2p0 monitor                iface = "p2p0";            }            if (VDBG) Log.d(TAG, "Dispatching event to interface: " + iface);            WifiMonitor m = mIfaceMap.get(iface);            if (m != null) {                if (m.mMonitoring) {                    if (m.dispatchEvent(eventStr, iface)) {                        mConnected = false;                        return true;                    }                    return false;                } else {                    if (DBG) Log.d(TAG, "Dropping event because (" + iface + ") is stopped");                    return false;                }            } else {                if (DBG) Log.d(TAG, "Sending to all monitors because there's no matching iface");                boolean done = false;                boolean isMonitoring = false;                boolean isTerminating = false;                if (eventStr.startsWith(EVENT_PREFIX_STR)                        && eventStr.contains(TERMINATING_STR)) {                    isTerminating = true;                }                for (WifiMonitor monitor : mIfaceMap.values()) {                    if (monitor.mMonitoring) {                        isMonitoring = true;                        if (monitor.dispatchEvent(eventStr, iface)) {                            done = true;                        }                    }                }                if (!isMonitoring && isTerminating) {                    done = true;                }                if (done) {                    mConnected = false;                }                return done;            }        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
1.wpa_supplicant发送上来的时间是一个字符串,这里需要对这个字符串做一个解析,找到对应接口的WifiMontor.
2.调用对应WifiMontor的事件分发方法:monitor.dispatchEvent(eventStr, iface)。
wifi的接口一般为wlan0,此时下面的方法会被调用:
    /* @return true if the event was supplicant disconnection */    private boolean dispatchEvent(String eventStr, 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(ANQP_DONE_STR)) {                try {                    handleAnqpResult(eventStr);                }                catch (IllegalArgumentException iae) {                    Log.e(TAG, "Bad ANQP event string: '" + eventStr + "': " + iae);                }            } else if (eventStr.startsWith(GAS_QUERY_PREFIX_STR)) {        // !!! clean >>End                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)) {                  // !!! <<End                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 (eventStr.startsWith(AUTH_EVENT_PREFIX_STR) &&                    eventStr.endsWith(AUTH_TIMEOUT_STR)) {                mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);            } 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(SCAN_FAILED_STR))            event = SCAN_FAILED;        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;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
部分时间会调用handleEvent(event, eventData);进一步处理:
   void handleEvent(int event, String remainder) {        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 SCAN_FAILED:                mStateMachine.sendMessage(SCAN_FAILED_EVENT);                break;            case UNKNOWN:                if (DBG) {                    logDbg("handleEvent unknown: " + Integer.toString(event) + "  " + remainder);                }                break;            default:                break;        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
这样我们之前的操作:
2扫描附近热点
startScan();之后,接受WifiManager.SCAN_RESULTS_AVAILABLE_ACTION的广播会触发,在这个广播中调用getScanResults()方法可以获得一个List,它里面的每一个条目就是一个可连接的热点。
wifi.startScan();
results = wifi.getScanResults();
为什么会有广播通知扫描结果已经可用了就有答案了。
我们startScan以后,wpa_supplicant扫描结束后会发送SCAN_RESULTS事件上来,在handleEvent方法中,检测到事件为SCAN_RESULTS后就向wifi状态机发送一个消息:mStateMachine.sendMessage(SCAN_RESULTS_EVENT);在wifi状态机中处理过程如下所示:
               case WifiMonitor.SCAN_FAILED_EVENT:                    maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered                    closeRadioScanStats();                    noteScanEnd();                    setScanResults();                    // when wpa_supplicant start, it will execute scan, lead to WifiStateMachine's scan command                    // operate failed, because wpa_supplicant's scan is ongoing, mIsFullScanOngoing still false,                    // it can not send ScanResultsBroadcast, app can not receive ScanResultsBroadcast, so that                    // sometime app refresh the ap list is slow in first open wifi, so now, when it receive                    // SCAN_RESULTS_EVENT, send ScanResultsBroadcast directly, to refresh ap list                    //if (mIsFullScanOngoing || mSendScanResultsBroadcast) {                    /* Just updated results from full scan, let apps know about this */                    boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT;                    sendScanResultsAvailableBroadcast(scanSucceeded);                    //}                    mSendScanResultsBroadcast = false;                    mIsScanOngoing = false;                    mIsFullScanOngoing = false;                    if (mBufferedScanMsg.size() > 0)                        sendMessage(mBufferedScanMsg.remove());                    break;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
1.使用setScanResults设置扫描的结果。
2.使用sendScanResultsAvailableBroadcast(scanSucceeded);发送扫描结果可用的广播。
综上,整个Android系统的wifi框架我们通过对源码的追踪,梳理了一遍。wifi框架中有两个非常重要的状态机:mWifiController 和mWifiStateMachine,他们相互配合,维护这wifi的各个状态。mWifiStateMachine内部使用WifiNative向wpa_supplicant发送各种命令。WifiStateMachine中还有一个WifiMonitor,它负责接收wpa_supplicant发送上来的事件。这样,结合事件的发送和接收,我们就理清了应用程序和wpa_supplicant交互的过程。

收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版