从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); }调用它内部类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交互的过程。
|