本文为读书笔记,整理自网络文献和源码
2 wifi framework分析
WIFI Settings应用程序位于
packages/apps/Settings/src/com/android/settings/wifi/
涉及到的文件:
WifiSettings.java
frameworks部分:
frameworks/base/services/java/com/android/server/
frameworks/base/wifi/java/android/net/wifi/
涉及到的文件有:
SystemServer.java
WifiManager.java
WifiService.java
WifiStateMachine.java
WifiMonitor.java
Wifinative.java
2.1、注册WifiService
frameworks/base/services/java/com/android/server/SystemServer.java
线程class ServerThread extends Thread中注册WifiService
try{
Slog.i(TAG, "Wi-FiService");
wifi = newWifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
} catch (Throwable e) {
reportWtf("starting Wi-FiService", e);
}
try {
Slog.i(TAG, "ConnectivityService");
connectivity = newConnectivityService(
context,networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
wifi.checkAndStartWifi();
wifiP2p.connectivityServiceReady();
} catch (Throwable e) {
reportWtf("startingConnectivity Service", e);
}
2.2、WifiService
frameworks/base/services/java/com/android/server/WifiService.java
wifiservice是整个框架的核心部分,application层触发事件后,会调用这个service里面的方法来处理事件,包括加载驱动,开启wpa_supplicant,扫描AP都是调用这个service里面的方法实现的,实际上这些方法最终调用的是wifistatemachine里面的方法去发送消息。由wifistatemachine里面的描述wifi事件的内部类去处理这些消息。
在这个类的构造方法中主要就是实例化了一个描述wifi状态机的类WifiStateMachine,重写了广播事件的onReceive方法。
2.3、WifiStateMachine
frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
wifiservice中的方法最终是调用WifiStateMachine这个service里面的方法来实现的,WifiStateMachine主要就是对sendmessage()的封装。在这个service中,需要传递到wpa_supplicant来实现wifi功能的命令,都在这个service中做了定义。针对每一个wifi状态,都声明了一个内部类去描述,比如描述加载驱动,开启wpa_supplicant等,每一个状态类都有三个方法构成enter(),processmessage(), 不过不同类的这三个方法里面的程序不同而已。WifiStateMachine的构造方法里面,主要的工作是实例化了wifi的监视器mWifiMonitor
= new WifiMonitor(this),这个监视器的作用下面再做解释,简单地讲,就是通过这个监视器,阻塞监听wpa_supplicant传递上来的信息,对信息进行处理后通知上层采取相应的形式去实现。在这个构造方法中,对每一个描述wifi状态的内部类的实例,都使用add()方法把这些内部类的实例添加到状态机中,这两项主要工作对应的代码如下:
mWifiMonitor = new WifiMonitor(this);
……
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);
之后,使用setInitialState(mInitialState)使wifi状态机进入初始化状态,并通过方法start()开启状态机。通过把各种wifi状态类的实例添加到wifi状态机,以后通过sendmessage(Message message)方法发送消息,参数message会写进消息队列汇总,wifi状态机会根据相应的message调用相应的wifi状态类里面的方法对消息进行处理。例如wifi驱动的加载。sendmessage(CMD_LOAD_DRIVER)发送加载驱动的消息到消息队列后,会触发wifi状态机的里面的状态类DriverLoadingState,调用里面的方法去加载驱动。
2.4 WifiMonitor
frameworks/base/wifi/java/android/net/wifi/WifiMonitor.java
前面已经简单介绍过,WifiMonitor这个类主要功能就是阻塞等待(监控)wpa_supplicant传上来的命令后根据命令来进行相应的处理。那么这个监视器是什么时候打开的呢,我们来分析它的打开流程。
在系统起来之后,systemserver把wifiservice 和connectivity的实例添加到android的service管理器,这前面已经介绍过,之后,调用wifiservice的方法
wifi.checkAndStartWifi();实际上调用了WifiStateMachine的方法setWifiEnabled(wifiEnabled),在这个方法里面,加载驱动,开启wpa_supplicant,对应的代码如下:
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));
}
}
之后wifi状态机WifiStateMachine就会进入DriverLoadedState状态,通过native层调用wifi.c开启wpa_supplicant的方法后就开启wifimonitor,也就是说,监视器的开启必须是
在驱动加载成功以及开启wpa_supplicant后才开启,相应的代码如下:
if(WifiNative.startSupplicant()) {
if (DBG) log("Supplicant startsuccessful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed tostart supplicant!");
sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0));
}
介绍下wifimonitor是如何阻塞监听wpasupplicant传过来的信息的,在监视器开启之后:在监视线层的循环体里面,调用wifi.c里面的waitForEvent()方法来监听接收
wpa_supplicant传过来的消息,相应的代码如下:
public void startMonitoring() {
new MonitorThread().start();
}
class MonitorThread extends Thread {
public MonitorThread() {
super("WifiMonitor");
}
public void run() {
if (connectToSupplicant()) {
// Send a message indicatingthat it is now possible to send commands
// to the supplicant
mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
} else {
mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
return;
}
//noinspection InfiniteLoopStatement
for (;;) {
String eventStr =WifiNative.waitForEvent();
……
根据字符串eventStr的不同值调用相应的处理流程来对事件进行不同的处理,上层做出相应的回应。
2.5 WifiNative
frameworks/base/wifi/java/android/net/wifi/WifiNativejava
这一个类里面是调用native层里面的对应方法的接口的集合,当我们在frameswork层希望与下层进行交互调用下层的方法的时候,都是先调用这个类里面相应的接口,比如开启wpa_supplicant,就是通过WifiNative.startSupplicant()这个方式来调用native层的android_net_wifi_startSupplicant,最终调用HAL层中的wifi.c里面的wifi_start_supplicant()来开启wpa_supplicanat。