之前看过android4.0版本的wifi启动流程,对比android4.4的版本启动还是有不少出入,下面将android4.4的wifi相关部分启动代码流程做如下分析:
软件平台:Android4.4
硬件平台:MTK6572
WifiService作为wifi的主service,也是从SystemServer的initAndLoop中启动:
public void initAndLoop() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
SystemClock.uptimeMillis());
/// M: BOOTPROF @{
mMTPROF_disable = "1".equals(SystemProperties.get("ro.mtprof.disable"));
addBootEvent(new String("Android:SysServerInit_START"));
/// @}
Looper.prepareMainLooper();
......
try {
Slog.i(TAG, "Wi-Fi Service");
wifi = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
}
......
}
根据代码我们得知调到了WifiService的构造函数中:
public WifiService(Context context) {
mContext = context;
mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);
mWifiStateMachine.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mSettingsStore = new WifiSettingsStore(mContext);
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
mClientHandler = new ClientHandler(wifiThread.getLooper());
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
mWifiController.start();
mBatchedScanSupported = mContext.getResources().getBoolean(
R.bool.config_wifi_batched_scan_supported);
registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);
if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
// Adding optimizations of only receiving broadcasts when wifi is enabled
// can result in race conditions when apps toggle wifi in the background
// without active user involvement. Always receive broadcasts.
registerForBroadcasts();
///M:
initializeExtra();
}
该构造函数首先是实例化一个WifiStateMachine,这个构造方法我们后续再做详细说明,之后创建了wifiThread线程,并调用了start方法开始执行此线程(实则是开启了Looper模式,java中每一个thread只能有一个Looper,一个Looper可以包含多个Handler和MQ,每一个Handler在添加到线程的Looper中时也都有自己相应的MQ,这样线程中的MQ就会按顺序的处理消息然后发送给与之绑定的Handler去处理msg),紧接着是把ClientHandler,WifiStateMachineHandler都添加到Looper中,后续实例化一个WifiController,并调用start,为什么它也有start?因为它继承自StateMachine。
接下来,WifiController的构造方法:
WifiController(Context context, WifiService service, Looper looper) {
super(TAG, looper);
mContext = context;
mWifiStateMachine = service.mWifiStateMachine;
......
addState(mDefaultState);
addState(mApStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
addState(mDeviceInactiveState, mStaEnabledState);
addState(mScanOnlyLockHeldState, mDeviceInactiveState);
addState(mFullLockHeldState, mDeviceInactiveState);
addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
addState(mNoLockHeldState, mDeviceInactiveState);
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
if (mSettingsStore.isScanAlwaysAvailable()) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
setLogRecSize(100);
setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_DEVICE_IDLE)) {
sendMessage(CMD_DEVICE_IDLE);
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
}
}
},
new IntentFilter(filter));
initializeAndRegisterForSettingsChange(looper);
}
将wifiservice中实例化的状态机赋值给本地状态机,然后调用addState方法添加了一系列的父子状态机状态,根据后续的if-else逻辑我们不难发现状态机被初始化为mApStaDisabledState状态(记住这是状态机第一个暂留的状态)。WifiController先说明到此,这一步主要的就是第一个初始化的状态机状态。
回过头我们继续看WifiService构造方法中的registerForBroadcast()方法:
private void registerForBroadcasts() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
}
这其中有一个对ACTION_SCREEN_ON事件的广播侦听,在收到该广播之后:
if (action.equals(Intent.ACTION_SCREEN_ON)) {
mWifiController.sendMessage(CMD_SCREEN_ON);
向WifiController发送了CMD_SCREEN_ON的MSG,然后我们回到WifiController,在上一步将WifiController的时候,我们记住了一个状态:mApStaDisabledState,该MSG就是发送给了这个状态的processMessage()方法,然并卵,我们在此方法中并未看到对CMD_SCREEN_ON的处理,根据状态机的特点,我们看该状态的父状态有没有做处理。父状态为DefaultState,这里边果然有处理该消息的逻辑:
case CMD_SCREEN_ON:
mAlarmManager.cancel(mIdleIntent);
mScreenOff = false;
mDeviceIdle = false;
///M: @{
mWifiStateMachine.setDeviceIdle(mDeviceIdle);
///@}
updateBatteryWorkSource();
break;
这里边我们着重记住一个变量的赋值,mDeviceIdle = false;后面我们继续WifiService的构造方法:
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);
if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
这里注册了一个捕捉ACTION_AIRPLANE_MODE_CHANGED的广播,接收到这个广播后,通过mWifiController发送一个CMD_AIRPLANE_TOGGLED的消息,来看看接收到这个消息的地方,还是在WifiController的当前状态mApStaDisabledState实现类的 processMessage方法中:
case CMD_AIRPLANE_TOGGLED:
///M: add WifiIpoOff@{
boolean wifiIpoOff = (msg.arg1==1) ? true: false;
boolean ipoStateChange= false;
if(mWifiIpoOff!=wifiIpoOff) ipoStateChange=true;
mWifiIpoOff = wifiIpoOff;
if(wifiIpoOff ==true){
SXlog.d(TAG,"ipooff don't enable wifi\n");
break;
}
if (mSettingsStore.isWifiToggleEnabled()) {
//@}
if (doDeferEnable(msg)) {
if (mHaveDeferredEnable) {
// have 2 toggles now, inc serial number an ignore both
mDeferredEnableSerialNumber++;
}
mHaveDeferredEnable = !mHaveDeferredEnable;
break;
}
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
///M: check scan always avaliable only when ipo change from ipo on to off
} else if (ipoStateChange ==true && mSettingsStore.isScanAlwaysAvailable() && mSettingsStore.isAirplaneModeOn()==false ) {
SXlog.d(TAG,"ipoStateChange = "+ipoStateChange + "isAirplaneModeOn= "+mSettingsStore.isAirplaneModeOn());
transitionTo(mStaDisabledWithScanState);
}
break;
注意当中对mDeviceIdle的判断,之前确定了该值为false,因此这个时候涉及到一个状态机状态的切换,切换至mDeviceActiveState,首先是进入该状态机的父状态机,StaEnabledState,此状态的enter方法如下:
@Override
public void enter() {
if (DBG) log(getName() + "\n");
mWifiStateMachine.setSupplicantRunning(true);
}
调用setSupplicantRunning(true),
public void setSupplicantRunning(boolean enable) {
if (enable) {
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
发出了一个CMD_START_SUPPLICANT的MSG,那么当前WifiStateMachine处于什么状态呢?我们切看一开始滞后解析的WifiStateMachine构造方法,状态机最初始暂存的一个状态是
setInitialState(mInitialState);
也就是InitialState状态的processMessage处理CMD_START_SUPPLICANT消息, case CMD_START_SUPPLICANT:
setWifiState(WIFI_STATE_ENABLING);
if (mWifiNative.loadDriver()) {
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
} catch (Exception e) {
loge("Failed to reload STA firmware " + e);
// continue
}
try {
// A runtime crash can leave the interface up and
// this affects connectivity when supplicant starts up.
// Ensure interface is down before a supplicant start.
mNwService.setInterfaceDown(mInterfaceName);
// Set privacy extensions
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
// IPv6 is enabled only as long as access point is connected since:
// - IPv6 addresses and routes stick around after disconnection
// - kernel is unaware when connected and fails to start IPv6 negotiation
// - kernel can start autoconfiguration when 802.1x is not complete
mNwService.disableIpv6(mInterfaceName);
} catch (RemoteException re) {
loge("Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
/* Stop a running supplicant after a runtime restart
* Avoids issues with drivers that do not handle interface down
* on a running supplicant properly.
*/
mWifiMonitor.killSupplicant(mP2pSupported);
if(mWifiNative.startSupplicant(mP2pSupported)) {
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
调用WifiNative的loadDriver方法,该方法定义在frameworks/base/core/jni/android_net_wifi_WifiNative.cpp中:
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
///M:@{
g_pItemListMutex = new pthread_mutex_t;
if (NULL == g_pItemListMutex) {
XLOGE("Failed to allocate memory for g_pItemListMutex!");
return JNI_FALSE;
}
pthread_mutex_init(g_pItemListMutex, NULL);
g_pCurrentSSID = new String8();
if (NULL == g_pCurrentSSID) {
XLOGE("Failed to allocate memory for g_pCurrentSSID!");
return JNI_FALSE;
}
char dbg[PROPERTY_VALUE_MAX] = {0};
if (property_get("wifi.jni.dbg", dbg, NULL) && strcmp(dbg, "true") == 0) {
DBG = true;
} else {
DBG = false;
}
///@}
return (::wifi_load_driver() == 0);
}
最后调到了hardware层的wifi.c中的接口:hardware/libhardware_legacy/wifi/wifi.c
int wifi_load_driver()
{
#ifdef WIFI_DRIVER_MODULE_PATH
char driver_status[PROPERTY_VALUE_MAX];
int count = 100; /* wait at most 20 seconds for completion */
if (is_wifi_driver_loaded()) {
return 0;
}
if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
return -1;
if (strcmp(FIRMWARE_LOADER,"") == 0) {
/* usleep(WIFI_DRIVER_LOADER_DELAY); */
property_set(DRIVER_PROP_NAME, "ok");
}
else {
property_set("ctl.start", FIRMWARE_LOADER);
}
sched_yield();
while (count-- > 0) {
if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
if (strcmp(driver_status, "ok") == 0)
return 0;
else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
wifi_unload_driver();
return -1;
}
}
usleep(200000);
}
property_set(DRIVER_PROP_NAME, "timeout");
wifi_unload_driver();
return -1;
#else
ALOGD("enter -->%s\n, uid=%d, gid=%d", __func__, getuid(), getgid());
property_set(DRIVER_PROP_NAME, "ok");
/*fix wifi_send_commadn bug*/
wifi_init_sync(&wifi_sync);
return 0;
#endif
}
调用insmod方法去loading相应path的ko文件,成功的话设置相应的property,返回0,失败的话返回-1。回到WifiStateMachine的CMD_START_SUPPLICANT的处理,在load完driver之后,会开启wpa服务。
mWifiMonitor.killSupplicant(mP2pSupported);
if(mWifiNative.startSupplicant(mP2pSupported)) {
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
调用WifiNative的接口,间接调用hardware层的wifi_start_supplicant方法,该方法在此不再赘述,只是通过property设置开启spa_supplicant service。之后是调用WifiMonitor的startMonitoring方法,并把状态机切换至mSupplicantStartingState状态:
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.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
} else {
if (DBG) Log.d(TAG, "connecting to supplicant");
int connectTries = 0;
while (true) {
if (mWifiNative.connectToSupplicant()) {
m.mMonitoring = true;
m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
new MonitorThread(mWifiNative, this).start();
mConnected = true;
break;
}
if (connectTries++ < 5) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
} else {
Log.d(TAG, "rmIfaceMap remove " + iface);
mIfaceMap.remove(iface);
///M:@{
if (!m.mInterfaceName.equals("ap0")) {
m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
}
///@}
Log.e(TAG, "startMonitoring(" + iface + ") failed! " );
break;
}
}
}
}
第一次执行,mConnected为false,走else通路,调用WifiNative.connectToSupplicant()方法,继而到hal层wifi_connect_to_supplicant()方法,此方法最终调用到了 wpa层的代码:wpa_ctl_open打开了两个连接:ctrl_conn和monitor_conn。
后边开启一个MonitorThread,我们看一下这个构造方法:
public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
super("WifiMonitor");
mWifiNative = wifiNative;
mWifiMonitorSingleton = wifiMonitorSingleton;
}
没有什么实质功能性实现,下面我们看其run方法:
public void run() {
//noinspection InfiniteLoopStatement
for (;;) {
String eventStr = mWifiNative.waitForEvent();
// Skip logging the common but mostly uninteresting scan-results event
if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
Log.d(TAG, "Event [" + eventStr + "]");
}
String iface = "p2p0";
WifiMonitor m = null;
mStateMachine = null;
if (eventStr.startsWith("IFNAME=")) {
int space = eventStr.indexOf(' ');
if (space != -1) {
iface = eventStr.substring(7,space);
Log.d(TAG, "iface " + iface);
m = mWifiMonitorSingleton.getMonitor(iface);
if(m==null)Log.d(TAG, "hcan get mm " + iface);
if (m == null && 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 ..
m = mWifiMonitorSingleton.getMonitor("p2p0");
}
eventStr = eventStr.substring(space + 1);
}
} else {
///M: if ap0 exist, it could be hotspot event
m = mWifiMonitorSingleton.getMonitor("ap0");
if(m!=null){
if(m.mMonitoring){
//we find hotspot active
}else{
//try p2p0
m = mWifiMonitorSingleton.getMonitor("p2p0");
}
}else{
// events without prefix belong to p2p0 monitor
m = mWifiMonitorSingleton.getMonitor("p2p0");
}
}
if (m != null) {
if (m.mMonitoring) {
mStateMachine = m.mWifiStateMachine;
} else {
if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
") is stopped");
continue;
}
}
if (mStateMachine != null) {
if (dispatchEvent(eventStr, m.mInterfaceName)) {
//M: when dispatchEvent=true means break from waitForEvent
//M: for hotspot clear hotspot data
if(m.mInterfaceName.equals("ap0")){
m.mMonitoring =false;
mWifiNative.closeSupplicantConnection();
Log.d(TAG, "ap0 get TEMINATING 1");
}
break;
}
} else {
if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id");
boolean done = false;
Iterator<Map.Entry<String, WifiMonitor>> it =
mWifiMonitorSingleton.mIfaceMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, WifiMonitor> e = it.next();
m = e.getValue();
mStateMachine = m.mWifiStateMachine;
if (dispatchEvent(eventStr,null)) {
done = true;
}
}
if (done) {
//M: for hotspot clear hotspot data
if(m.mInterfaceName.equals("ap0")){
m.mMonitoring =false;
mWifiNative.closeSupplicantConnection();
Log.d(TAG, "ap0 get TEMINATING 2");
}
// After this thread terminates, we'll no longer
// be connected to the supplicant
if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
mWifiMonitorSingleton.mConnected = false;
break;
}
}
}
}
这里调用了WifiNative的waitForEvent方法,这个方法通过jni调用本地方法读取wpa_supplicant的消息,并转发出去。
while (it.hasNext()) {
Map.Entry<String, WifiMonitor> e = it.next();
m = e.getValue();
mStateMachine = m.mWifiStateMachine;
if (dispatchEvent(eventStr,null)) {
done = true;
}
}
后面dispatchEvent的实现:
/* @return true if the event was supplicant disconnection */
private boolean dispatchEvent(String eventStr, String iface) {
if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
if ((eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR))
///M:@{
|| (eventStr.startsWith(AUTHENTICATION_TIMEOUT_PREFIX_STR)
&& 0 < eventStr.indexOf(AUTHENTICATION_TIMEOUT_STR))) {
///@}
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
} 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, iface);
///M:@{
} else if (eventStr.startsWith(EAP_FAST_NEW_PAC_UPDATED)) {
mStateMachine.sendMessage(NEW_PAC_UPDATED_EVENT);
///M: whole chip reset fail
} else if (eventStr.startsWith(WHOLE_CHIP_RESET_FAIL_STRING)){
mStateMachine.sendMessage(WHOLE_CHIP_RESET_FAIL_EVENT);
/** M: NFC Float II @{ */
} else if (eventStr.startsWith(WPS_ER_ENROLLEE_ADD_STR)) {
mStateMachine.sendMessage(WPS_ER_ENROLLEE_ADD_EVENT, eventStr);
} else if (eventStr.startsWith(WPS_ER_AP_ADD_STR)) {
mStateMachine.sendMessage(WPS_ER_AP_ADD_EVENT, eventStr);
/** } */
}
///@}
else {
if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
}
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");
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;
///M: add
handleP2pEvents(eventStr);
} 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;
///M:@{
else if (eventName.equals(WAPI_NO_CERTIFICATION_STRING))
event = NO_CERTIFICATION;
///@}
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 == STATE_CHANGE) {
handleSupplicantStateChange(eventData);
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
} else if (event == TERMINATING) {
Log.d(TAG, "event == TERMINATING " );
/**
* Close the supplicant connection if we see
* too many recv errors
*/
if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
if (++mRecvErrors > MAX_RECV_ERRORS) {
if (DBG) {
Log.d(TAG, "too many recv errors, closing connection");
}
} else {
return false;
}
}
// notify and exit
if(iface!=null && !iface.equals("ap0")){
mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
}
Log.d(TAG, "Exit because of receiving terminating for " + getName() + ", id:" + getId());
return true;
} else if (event == EAP_FAILURE) {
if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
}
} else if (event == ASSOC_REJECT) {
mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);
} else {
handleEvent(event, eventData);
}
mRecvErrors = 0;
return false;
}
经过一系列处理调用handleEvent方法,
void handleEvent(int event, String 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;
///M: @{
case NO_CERTIFICATION:
mStateMachine.sendMessage(WAPI_NO_CERTIFICATION_EVENT);
break;
///@}
case UNKNOWN:
break;
}
}
以SCAN_RESULTS 为例,状态机发送SCAN_RESULTS_EVENT消息,这个状态机为WifiStateMachine对象,状态机此时为SupplicantStartedState,看下该状态下的processMessage方法:
case WifiMonitor.SCAN_RESULTS_EVENT:
setScanResults();
if (mWifiFwkExt.hasCustomizedAutoConnect()) {
mShowReselectDialog = false;
Xlog.d(TAG, "SCAN_RESULTS_EVENT, mScanForWeakSignal:" + mScanForWeakSignal);
if (mScanForWeakSignal) {
showReselectionDialog();
}
mDisconnectNetworkId = INVALID_NETWORK_ID;
}
sendScanResultsAvailableBroadcast();
mScanResultIsPending = false;
break;
这里会把扫描的结果以广播的形式发送给接受者,sendScanResultsAvailableBroadcast()方法:
private void sendScanResultsAvailableBroadcast() {
noteScanEnd();
Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(IWifiFwkExt.EXTRA_SHOW_RESELECT_DIALOG_FLAG, mShowReselectDialog);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
至此,大体流程结束。。。