这几天闲着没事,我就随便拿起Android源码看看。以下要讲的是在ICS中wifi初始化的一些流程。
涉及的文件有:
SystemServer.Java
WifiSettings.java
WifiEnabler.java
WifiManager.java
WifiService.java
WifiStateMachine.java
android_net_wifi_wifi.cpp
wifi.c
首先从SystemServer.java开始,它做了3个动作:
1.添加注册ConnectivityService连接服务,它跟所有手机的无线通信都有联系,包括wifi,蓝牙,2g网络,3g网络等
connectivity = new ConnectivityService( context, networkManagement, networkStats, networkPolicy); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
2.管理开机wifi开启与否的问题
wifi.checkAndStartWifi();
public void checkAndStartWifi() { mAirplaneModeOn.set(isAirplaneModeOn()); mPersistWifiState.set(getPersistedWifiState()); boolean wifiEnabled = shouldWifiBeEnabled() || testAndClearWifiSavedState(); setWifiEnabled(wifiEnabled); mWifiWatchdogStateMachine = WifiWatchdogStateMachine. makeWifiWatchdogStateMachine(mContext); }
3.添加注册wifi的核心服务wifiservice
wifi = new WifiService(context); ServiceManager.addService(Context.WIFI_SERVICE, wifi);
好了,机器启动的时候动作就这些。要开启wifi,还需要人在设置界面进行开启。·
下面将一步步介绍wifi是怎样开启起来的
进入wifi设置界面,相关文件WifiSettings.java
开启Wifi的组件是一个CompoundButton,跟它关联起来的是一个WifiEnabler.java类,它是在WifiSettings里面初始化的
public void onActivityCreated(Bundle savedInstanceState) { mWifiEnabler = new WifiEnabler(activity, actionBarSwitch);
}
当用户点击wifi的开启按钮时候,会触发WifiEnabler里面的onCheckedChanged函数
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (mWifiManager.setWifiEnabled(isChecked)) { mSwitch.setEnabled(false); } else { Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show(); } 在onCheckedChanged函数里面,调用了WifiManager的setWifiEnabled方法
public boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(enabled); } catch (RemoteException e) { return false; } }
它返回的是mService.setWifiEnabled(enabled),这里的mService是WifiService的代理,所以它实际调用的是wifiService里面的setWifiEnabled函数
public class WifiService extends IWifiManager.Stub ,我们可以看到WifiService继承一个接口IWifiManager.Stub,凡是继承了像这种形式写法的接口服务,都可以进行远程调用,这就是android内部的aidl通信。接下来进入wifiservice
public synchronized boolean setWifiEnabled(boolean enable) { mWifiStateMachine.setWifiEnabled(enable); }
可以看到,又进入WifiStateMachine的setWifiEnabled方法,mWifiStateMachine是在Wifiservice的构造函数完成初始化 的
WifiService(Context context) { mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName); }
先介绍一下WifiStateMachine这个类,光看名字就知道wifi状态机,它里面记录了wifi的各种状态,driverUnloadedstate、mDriverUnloadingState、mDriverLoadingState、mDriverLoadedState、mSupplicantStartingState,每种状态都有enter()、exit()、processMessage()3个函数,分别处理进入该状态,退出该状态的动作,以及消息处理。在WifiStateMachine构造函数里面,它把所有状态都添加进状态机去,形成一个状态树,并在结尾出启动这个状态机工作。
public WifiStateMachine(Context context, String wlanInterface) { addState(mDefaultState); addState(mInitialState, mDefaultState); addState(mDriverUnloadingState, mDefaultState); addState(mDriverUnloadedState, mDefaultState); addState(mDriverFailedState, mDriverUnloadedState); addState(mDriverLoadingState, mDefaultState); addState(mDriverLoadedState, mDefaultState); addState(mSupplicantStartingState, mDefaultState); addState(mSupplicantStartedState, mDefaultState); addState(mDriverStartingState, mSupplicantStartedState); addState(mDriverStartedState, mSupplicantStartedState); addState(mScanModeState, mDriverStartedState); addState(mConnectModeState, mDriverStartedState); addState(mConnectingState, mConnectModeState); addState(mConnectedState, mConnectModeState); addState(mDisconnectingState, mConnectModeState); addState(mDisconnectedState, mConnectModeState); addState(mWaitForWpsCompletionState, mConnectModeState); addState(mDriverStoppingState, mSupplicantStartedState); addState(mDriverStoppedState, mSupplicantStartedState); addState(mSupplicantStoppingState, mDefaultState); addState(mSoftApStartingState, mDefaultState); addState(mSoftApStartedState, mDefaultState); addState(mTetheringState, mSoftApStartedState); addState(mTetheredState, mSoftApStartedState); addState(mSoftApStoppingState, mDefaultState); addState(mWaitForP2pDisableState, mDefaultState); 。。。。。。。。。。
start();
}
具体状态机是如何工作的,这篇文章有很详细的介绍,我就不累赘了。
http://archive.cnblogs.com/a/2424626/
我们再回到mWifiStateMachine.setWifiEnabled(enable)函数;
public void setWifiEnabled(boolean enable) { mLastEnableUid.set(Binder.getCallingUid()); if (enable) { /* Argument is the state that is entered prior to load */ sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0)); sendMessage(CMD_START_SUPPLICANT); } else { sendMessage(CMD_STOP_SUPPLICANT); /* Argument is the state that is entered upon success */ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0)); } }
它做了两个动作,向状态机发送了2个消息
sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));加载驱动
sendMessage(CMD_START_SUPPLICANT);开启supplicant
它在哪里处理的呢?
状态机构造函数初始化时候,设置有个一个初始状态
setInitialState(mInitialState);
我们进入mInitialState状态看看
public void enter() { if (WifiNative.isDriverLoaded()) { transitionTo(mDriverLoadedState); } else { transitionTo(mDriverUnloadedState); } 因为最开始驱动都是没有加载的,所以进入transitionTo(mDriverUnloadedState);
transitionTo函数是状态切换的函数。
继续mDriverUnloadedState
class DriverUnloadedState extends State { @Override public boolean processMessage(Message message) { switch (message.what) { case CMD_LOAD_DRIVER: mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING); transitionTo(mWaitForP2pDisableState); break; case WifiP2pService.P2P_ENABLE_PENDING: mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED); break; default: return NOT_HANDLED; } EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); return HANDLED; } }
这里会处理刚才的CMD_LOAD_DRIVER这个消息,继续切换到mWaitForP2pDisableState
class WaitForP2pDisableState extends State { @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); switch(message.what) { case WifiP2pService.WIFI_ENABLE_PROCEED: //restore argument from original message (CMD_LOAD_DRIVER) message.arg1 = mSavedArg; transitionTo(mDriverLoadingState);
break;
}
状态继续切换到mDriverLoadingState
class DriverLoadingState extends State { @Override public void enter() { new Thread(new Runnable() { public void run() { mWakeLock.acquire(); //enabling state switch(message.arg1) { case WIFI_STATE_ENABLING: setWifiState(WIFI_STATE_ENABLING); break; case WIFI_AP_STATE_ENABLING: setWifiApState(WIFI_AP_STATE_ENABLING); break; } if(WifiNative.loadDriver()) { if (DBG) log("Driver load successful"); sendMessage(CMD_LOAD_DRIVER_SUCCESS); } else { loge("Failed to load driver!"); switch(message.arg1) { case WIFI_STATE_ENABLING: setWifiState(WIFI_STATE_UNKNOWN); break; case WIFI_AP_STATE_ENABLING: setWifiApState(WIFI_AP_STATE_FAILED); break; } sendMessage(CMD_LOAD_DRIVER_FAILURE); } mWakeLock.release(); } }).start(); } 这里回调用WifiNative.loadDriver()加载驱动,成功后发送消息CMD_LOAD_DRIVER_SUCCESS,否则CMD_LOAD_DRIVER_FAILURE,进入JNI
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject) { return (jboolean)(::wifi_load_driver() == 0); }
会继续到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 */ int status = -1; if (is_wifi_driver_loaded()) { return 0; } /* ensure that wlan driver config file exists (if specified) */ if (ensure_wlan_driver_config_file_exists()) { return -1; } property_set(DRIVER_PROP_NAME, "loading"); if(system(SDIO_POLLING_ON)) LOGW("Couldn't turn on SDIO polling: %s", SDIO_POLLING_ON); if ('\0' != *DRIVER_SDIO_IF_MODULE_PATH) { if (insmod(DRIVER_SDIO_IF_MODULE_PATH, DRIVER_SDIO_IF_MODULE_ARG) < 0) { goto end; } } if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) { if ('\0' != *DRIVER_SDIO_IF_MODULE_NAME) { rmmod(DRIVER_SDIO_IF_MODULE_NAME); } goto end; } 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) { status = 0; goto end; } else if (strcmp(driver_status, "failed") == 0) { _wifi_unload_driver(); goto end; } } usleep(200000); } property_set(DRIVER_PROP_NAME, "timeout"); wifi_unload_driver(); end: system(SDIO_POLLING_OFF); return status; #else property_set(DRIVER_PROP_NAME, "ok"); return 0; #endif }
这里有几个比较重要的宏
#define WIFI_DRIVER_MODULE_PATH "/system/lib/modules/wlan.ko"驱动模块地址
static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf"; supplicant配置文件
在这里wifi.c会跟wpa_supplicant通信,加载驱动
来看另一个消息sendMessage(CMD_START_SUPPLICANT);在DriverLoadedState处理
class DriverLoadedState extends State { @Override public boolean processMessage(Message message) { case CMD_START_SUPPLICANT: try { mNwService.wifiFirmwareReload(mInterfaceName, "STA"); } catch (Exception e) { loge("Failed to reload STA firmware " + e); // continue } try { mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); } catch (RemoteException re) { loge("Unable to change interface settings: " + re); } catch (IllegalStateException ie) { loge("Unable to change interface settings: " + ie); } if(WifiNative.startSupplicant()) { if (DBG) log("Supplicant start successful"); mWifiMonitor.startMonitoring(); transitionTo(mSupplicantStartingState); } else { loge("Failed to start supplicant!"); sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); } break;
继续调用JNI,WifiNative.startSupplicant(),过程差不多最后在wifi.c处理
int wifi_start_supplicant() { return wifi_start_supplicant_common(SUPP_CONFIG_FILE); } int wifi_start_supplicant_common(const char *config_file)
。。。。。。。
最后也是在这里跟Wpa_supplicant驱动通信
在wifi状态发生改变的时候,wifistatemachine会通过setwifistate发送WIFI_STATE_CHANGED_ACTION消息通知外面
private void setWifiState(int wifiState) {
final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); mContext.sendStickyBroadcast(intent); }
例如在驱动加载状态
class DriverLoadingState extends State { new Thread(new Runnable() { public void run() { mWakeLock.acquire(); //enabling state switch(message.arg1) { case WIFI_STATE_ENABLING: setWifiState(WIFI_STATE_ENABLING); break; case WIFI_AP_STATE_ENABLING: setWifiApState(WIFI_AP_STATE_ENABLING); break; } }
class SupplicantStartingState extends State { public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); switch(message.what) { case WifiMonitor.SUP_CONNECTION_EVENT: if (DBG) log("Supplicant connection established"); setWifiState(WIFI_STATE_ENABLED); }
在wifisettings里面也有广播监听器
public WifiSettings() { mFilter = new IntentFilter(); mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); mFilter.addAction(WifiManager.ERROR_ACTION); mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { handleEvent(context, intent); } }; mScanner = new Scanner(); } 当接受到广播会相应处理handleEvent
private void handleEvent(Context context, Intent intent) { String action = intent.getAction(); if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)); } }
更新wifi状态
private void updateWifiState(int state) { getActivity().invalidateOptionsMenu(); switch (state) { case WifiManager.WIFI_STATE_ENABLED: mScanner.resume(); return; // not break, to avoid the call to pause() below case WifiManager.WIFI_STATE_ENABLING: addMessagePreference(R.string.wifi_starting); break; case WifiManager.WIFI_STATE_DISABLED: addMessagePreference(R.string.wifi_empty_list_wifi_off); break; } mLastInfo = null; mLastState = null; mScanner.pause(); } 比如 case WifiManager.WIFI_STATE_ENABLED:当WIFI可用通知接受到的时候 mScanner.resume();
Scanner resume函数
void resume() { if (!hasMessages(0)) { sendEmptyMessage(0); } }
再看处理
@Override public void handleMessage(Message message) { if (mWifiManager.startScanActive()) { mRetry = 0; } else if (++mRetry >= 3) { mRetry = 0; Toast.makeText(getActivity(), R.string.wifi_fail_to_scan, Toast.LENGTH_LONG).show(); return; } sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS); } }
会调用mWifiManager.startScanActive()进行ap的扫描
所以当你点击wifi按钮,到驱动加载完成,发出WIFI_STATE_ENABLED消息的时候,
设置里面会进行扫描ap的动作