Android-wifi学习2---android4.0 wifi 框架
来源:互联网 发布:怎么算包皮正常知乎 编辑:程序博客网 时间:2024/06/14 17:51
wifi相关的文件位置:
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
Wifinative.java
JNI部分:
frameworks/base/core/jni/android_net_wifi_Wifi.cpp
wifi管理库。
hardware/libhardware_legary/wifi/
涉及到的文件:
Wifi.c
wifi用户空间的程序和库:
external/wpa_supplicant_8/
生成守护进程wpa_supplicant
一Framesworks层相应的类以及处理流程的介绍
1注册service
Android系统起来后,SystemServer进程的名字实际上是system_server,是由Zygote进程创建的,SystemServer进程创建后会调用SystemServer.java中的main函数,main函数回调SystemServer中的init2函数,启动android services,在init2函数中启动一个ServerThread线程,在该线程的run函数中会创建一系列的Android Services,将与网络以及wifi相关的service在systemserver.java里面的线程systemthread里面注册,也就是把网络与wifi相关的service的实例用ServiceManager.addService(String name, IBinder service)进行注册,与wifi相关的就是wifiservice类,相关代码如下:
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);
}
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
wifi.checkAndStartWifi();
wifiP2p.connectivityServiceReady();
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
}
上面的代码告诉我们将与网络相关的service实例networkStats与networkPolicy与connectivityservice相关联,所谓相关联,我的理解是,在networkStats与networkPolicy这两个实例对应的service类中定义一个ConnectivityService类的父类的实例;
2 Wifiservice简介
wifiservice是整个框架的核心部分,application层触发事件后,会调用这个service里面的方法来处理事件,包括加载驱动,开启wpa_supplicant,扫描AP都是调用这个service里面的方法实现的,实际上这些方法最终调用的是wifistatemachine里面的方法去发送消息。由wifistatemachine里面的描述wifi事件的内部类去处理这些消息。
在这个类的构造函数中主要就是实例化了一个描述wifi状态机的类wifistatumachine ,重写了广播事件的onReceive函数。
3Wifistatusmachine简介以及android wifi信息传递机制与流程简介。
上面已经提到,wifiservice中的方法最终是调用这个service里面的方法来实现的,主要就是对sendmessage()的封装。在这个service中,需要传递到wpa_supplicant来实现wifi功能的命令,都在这个service中做了定义。针对每一个wifi状态,都声明了一个内部类去描述,比如描述加载驱动,开启wpa_supplicant等,每一个状态类都有三个函数构成,enter(),statue().processmessage(),只不过不同类的这三个函数里面的程序不同而已。Wifistatusmachine的构造函数里面,主要的工作是实例化了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,调用里面的方法去加载驱动。
4Wifimonitor
前面已经简单介绍过,这个类主要功能就是阻塞等待wpa_supplicant传上来的命令后根据命令来进行相应的处理。那么这个监视器是什么时候打开的呢,我们来分析它的打开流程。
在系统起来之后,把wifiservice 和connectivity的实例添加到android的service管理器,这前面已经介绍过,之后,调用wifiservice的方法wifi.checkAndStartWifi();实际上调用了wifimachine的方法setWifiEnabled(wifiEnabled),在这个方法里面,加载驱动,开启wpa_supplicant,对应的代码如下:
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状态机就会进入DriverLoadedState 状态,通过native层调用wifi.c开启wpa_supplicant的函数后就开启wifimonitor,也就是说,监视器的开启必须是在驱动加载成功以及开启wpa_supplicant后才开启,相应的代码如下:
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));
}
介绍下wifimonitor是如何阻塞监听wpasupplicant传过来的信息的,在监视器开启之后:在监视线层的循环体里面,调用wifi.c里面的waitForEvent()函数来监听接收wpa_supplicant传过来的消息,相应的代码如下:
public void run() {
if (connectToSupplicant()) {
// Send a message indicating that 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的不同值调用相应的处理流程来对事件进行不同的处理,上层做出相应的回应。
5Wifinative
这一个类里面是调用native层里面的对应函数的接口的集合,当我们在frameswork层希望与下层进行交互调用下层的函数的时候,都是先调用这个类里面相应的接口,比如开启wpa_supplicant,就是通过WifiNative.startSupplicant()这个方式来调用native层的android_net_wifi_startSupplicant,最终调用wifi.c里面的wifi_start_supplicant()来开启wpa_supplicanat。
二JNI层
对应的文件是android_net_wifi_WiFi.cpp。这个文件里面是调用wifi.c里面对应函数的接口的集合,提供给frameswork层的类Wifinative里面的函数调用。
三wifi.c文件
简单地说,这个文件主要是实现驱动的加载和卸载,wpa_supplicant的开启。我们公司为配合skyworth的平台对多个dongle的支持,对wifi.c做了部分修改,修改部分主要是驱动的加载部分。
在本文件中重新定义了一个结构体dongle_info,结构体的成员是三个函数指针,针对不同的wifi设备,对每一个wifi设备都重写一个文件,文件路径是hardware\amlogic\wifi\dongle_info,在文件中主要是实现三个函数,分别是xxx_loaddriver,xxx_unloaddriver,xxx_search,三个函数,同时,定义一个存储vid和pid号的数组,这个数组的作用是,通过判断插入的usb wifi设备的vid_pid号是否与该表中的某一组vid_pid号相等来决定是否加载对应的驱动。在wifi.c中,定义一个dongle_info 类型的数组,把各个wifi设备的xxx_loaddriver,xxx_unloaddriver,xxx_search赋值给数组成员。本文件主要有以下几个函数比较重要,重点介绍下,分为三个部分:
驱动的加载卸载:
wifi_load_driver():驱动的加载。我们的wifi驱动都是编译成ko文件,wifi.h开头定义了ko文件储存的位置#define WIFI_DRIVER_MODULE_PATH "/system/lib" 。这个函数会被上层调用,驱动加载的原理就是通过判断插入usb wifi设备的vid_pid号是否与相对应的vid_pid表的某一组vid_pid号相等来决定是否加载对应的驱动,如果有一组相等,则加载驱动成功。
wpa_unload_driver()
Wpa_supplicant相关:
wifi_start_supplicant():上层要开启wpa_supplicant,直接调用的是这个函数,这个函数实际上是调用wifi_start_supplicant_common(const char *config_file)
wifi_start_supplicant_common(const char *config_file):这个函数实际上为wifi.c进程与wpa_supplicant进程相连做一些准备工作。
wifi_connect_to_supplicant():wifi.c进程与wpa_supplicant进程进行通信,他们之间采用socket的方式来实现进程间通信,计算机网络的客户端与服务器的用socket通信的实现方法相信每一个人都很熟悉,进程间用socket来进行通信的实现方法也是类似,包括创建套接口,绑定,连接,具体就不详细介绍了。函数调用的是wpa_ctrl.c里面的wpa_ctrl_open(const char *ctrl_path)函数来实现。
数据的传输:
wifi_command(const char *command, char *reply, size_t *reply_len):这个函数被jni调用,主要是上层发送命令通过这个函数传递给wpa_supplicant。这个函数实际上是调用wifi_send_command(ctrl_conn, command, reply, reply_len)函数。
wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len):发送上层传递过来的命令给wpa_supplicant;
wifi_wait_for_event(char *buf, size_t buflen):上层调用这个函数阻塞等待wpa_supplicant传递上来的信息,主要是调用wifi_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)来实现。
wifi_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len):调用wpa_ctrl.c中的wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)来接收wpa_supplicant传递过来的信息。
四wpasupplicant层
wpa_supplicant本是开源项目源码,被谷歌修改后加入android平台,它主要是用来支持WEP,WPA/WPA2和WAPI无线协议和加密认证的,而实际上的工作内容是通过socket(不管是wpa_supplicant与上层还是wpa_supplicant与驱动都采用socket通讯)与驱动交互上报数据给用户,而用户可以通过socket发送命令给wpa_supplicant调动驱动来对WiFi芯片操作。 简单的说,wpa_supplicant就是WiFi驱动和用户的中转站外加对协议和加密认证的支持。
这里主要介绍的是wpa_supplicant与驱动接口的联系。在drivers.h中定义了一个wpa_driver_ops结构体,结构体成员是一个个函数指针,这些指针在哪里赋值呢?接着往下看,在driviers.c里面都是不同驱动操作接口的集合wpa_driver_XXX_ops变量;然后就是定义一个驱动操作接口集合的数组,根据宏定义添加对应的驱动操作接口集合的变量。不同的驱动接口采用不同的文件来实现,如果wpa_supplicant使用的是wext接口与驱动进行通信,那么就在driver_wext.c文件里面对wpa_driver_ops结构体里面的成员赋值,这些成员指针指向的函数也在这个文件里面实现。代码如下:
const struct wpa_driver_ops wpa_driver_wext_ops = {
.name = "wext",
.desc = "Linux wireless extensions (generic)",
.get_bssid = wpa_driver_wext_get_bssid,
.get_ssid = wpa_driver_wext_get_ssid,
.set_key = wpa_driver_wext_set_key,
.set_countermeasures = wpa_driver_wext_set_countermeasures,
.scan2 = wpa_driver_wext_scan,
.get_scan_results2 = wpa_driver_wext_get_scan_results,
.deauthenticate = wpa_driver_wext_deauthenticate,
.disassociate = wpa_driver_wext_disassociate,
.associate = wpa_driver_wext_associate,
.init = wpa_driver_wext_init,
.deinit = wpa_driver_wext_deinit,
.add_pmkid = wpa_driver_wext_add_pmkid,
.remove_pmkid = wpa_driver_wext_remove_pmkid,
.flush_pmkid = wpa_driver_wext_flush_pmkid,
.get_capa = wpa_driver_wext_get_capa,
.set_operstate = wpa_driver_wext_set_operstate,
.get_radio_name = wext_get_radio_name,
#ifdef ANDROID
.signal_poll = wpa_driver_signal_poll,
.driver_cmd = wpa_driver_wext_driver_cmd,
#endif
};
那么还有一个疑问,wpa_supplicant怎么知道使用哪个驱动接口呢?在wpa_supplicant中的在wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,struct wpa_interface *iface)函数里面
driver = iface->driver;
之后调用wpa_supplicant_set_driver(wpa_s, driver)来设置wpa_supplicant使用哪个接口与驱动进行通信。
wpa_supplicant是为不同驱动和操作系统具有更好移植性而被设计的,以便在wpa_supplicant层不用实现驱动的具体接口就可以添加新的驱动程序;在wpa_supplicant结构中有一个wpa_drv_ops类型的drvier成员,在wpa_supplicant进程中,经常通过Wpa_supplicant_XXX函数传递wpa_supplicant实例指针wpa_s参数给wpa_drv_XXX函数来调用它,在wpa_drv_XX中会通过wpa_s->driver->XXX()的流程来调用通用驱动接口。
- Android-wifi学习2---android4.0 wifi 框架
- Android WiFi框架学习--打开WiFi
- Android WiFi框架学习-打开WiFi
- Android4.0 WIFI分析
- Android之Wifi学习(2)------连接Wifi
- Android之Wifi学习(2)------连接Wifi
- Android之Wifi学习(2)------连接Wifi
- android4.0 wifi启动流程
- Android4.0 WiFi 源码解读
- Android4.0 WIFI文档翻译
- android中wifi框架:::
- android 2.2 wifi 框架
- Android WIFI 框架分析
- Android WIFI框架分析
- Android wifi框架
- Android Wifi框架
- Android WIFI框架分析(2)
- Android WIFI框架分析(2)
- oracle 批量查询DDL
- oracle with 用法
- Oracle 中文转为拼音
- POJ 1504反转相加再反转
- oracle 多表插入
- Android-wifi学习2---android4.0 wifi 框架
- 站位
- Flex 饼图PieChart
- 使用多个静态库在连接时出现大量函数未定义
- oracle 删除重复记录
- oracle 创建临时表的几种方法
- char型数据
- oracle 闪回查询
- apache 2.2 + tomcat 6.0.35 建立集群