一、Wi-Fi各层文件路径
1、WifiSettings部分(Java应用层)
packages/apps/Settings/src/com/android/settings/wifi/
WifiSettings.java & WifiEnabler.java
2、Java Framework部分
frameworks/base/services/java/com/android/server/WifiService.java
frameworks/base/wifi/java/android/net/wifi/
WifiManager.java & WifiMonitor.java & WifiStateMachine.java &WifiNative.java
3、Wifi的JNI部分
frameworks/base/core/jni/android_net_wifi_Wifi.cpp
4、 Wifi的HAL(硬件抽象层)代码
hardware/libhardware_legary/wifi/wifi.c
5、 wpa_supplicant的源码部分
vendor/******/common/external/p2p_supplicant_8/
vendor/******/common/external/wpa_supplicant_8/
注:第1、2点只是针对“开启wifi”这一过程列出的部分主要文件。
二、相关文件介绍
1、WifiSettings & WifiEnabler
? 都属于应用程序层,是对相关操作结果的一个视觉呈现。主要负责界面初始化、接收底层事件消息进行界面更新、发出相应命令等。
2、WifiManager & WifiService & WifiStateMachine & WifiMonitor & WifiNative
? WifiManager:是Wi-Fi部分对外的接口,通过它来访问Wi-Fi的核心功能。
? WifiService:是Wi-Fi部分的核心,负责Wi-Fi整个流程的控制。
? WifiStateMachine:继承了StateMachine(一个层次结构的状态机,可以处理一些消息,并维护一个层次结构的状态)。它开始处于初始状态(InitialState),可以在不同的状态之间进行转换,需要通过延后deferMessage()+状态切换transitionTo()才能处理同一个message。在WifiStateMachine中,下发了加载驱动和启动supplicant命令,启动了WifiMonitor。Wifi状态机层次结构图如下:
? WifiMonitor:开启一个MonitorThread来实现事件的轮询,而轮询的关键函数是WifiNative.waitForEvent()。WifiMonitor将接收到的底层事件转换成WifiStateMachine所能识别的消息,然后将消息发送给WifiStateMachine。
? WifiNative:封装了一系列本地调用的接口函数,通过JNI调用C++代码。
3、android_net_wifi_Wifi.cpp
? 这里实现的本地函数,除了register_android_net_wifi_WifiManager(JNIEnv* env)是调用AndroidRuntime里的函数,用来注册本地方法,其他都是通过调用wpa_supplicant适配层的接口来实现的。
4、wifi.c
? 作为Wi-Fi部分的硬件抽象层来使用,主要用于与wpa_supplicant守护进程的通信,它实现了驱动加载、命令、消息监控等功能。它包含了wpa_supplicant的头文件wpa_ctrl.h,。
? 它有两个非常重要的接口函数:
1) int wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len)是对wifi_send_command()的封装,wifi_send_command()通过wpa_ctrl_request()直接把命令转发给wpa_supplicant进程,并返回结果。
2) int wifi_wait_for_event(const char *ifname, char *buf, size_t buflen)是对wifi_wait_on_socket()的封装,wifi_wait_on_socket()调用wpa_ctrl_recv()来接收上一次wpa_supplicant上报的消息。如果没有消息则阻塞于此。上层会通过循环来读取每一个上报的消息。
5、wpa_ctrl.c & ctrl_iface_unix.c & ctrl_iface.c & l2_packet_linux.c
? wpa_ctrl.c:它是一个单独的以C语言文件形式的小程序库,wpa_supplicant实现了一系列的控制接口,而它提供辅助函数使得上行控制接口便于使用。外部程序可以链接到这个文件,然后就可以使用wpa_ctrl.h中声明的库函数与wpa_supplicant相互作用。其主要工作是通过unix domain socket建立一个control interface的client结点,与wpa_supplicant的server结点通信。
? ctrl_iface.unix.c:实现wpa_supplicant的unix domain socket通信机制中的server结点,完成对client结点的响应。其中最主要的两个函数为:
1) static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx):接收并解析client发送的request命令,然后根据不同的命令调用底层不同的处理函数,将获得的response回馈给client结点。
2) static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, int level, const char *buf, size_t len):向注册的monitor interface主动发送event事件。
? ctrl_iface.c:主要实现了各种request命令的底层处理函数。
Note:上行接口--wpa_supplicant提供两种由外部模块获取信息的方式:一种是外部模块通过发送request命令然后获取response的问答模式;另一种是wpa_supplicant主动向外部发送event事件,由外部模块监听接收。外部模块通过调用wpa_ctrl_open()两次,建立两个control interface接口,一个为ctrl interface,用于发送命令,获取消息;另一个为monitor interface,用于监听接收来自wpa_supplicant的event。此举可以降低通信的耦合性,避免response和event的相互干扰。
6、drivers.c & driver.h & driver_wext.c & driver_wext.h
? drivers.c:驱动接口列表,drivers.c文件中必须注册一个wpa_driver_ops结构体指针,driver.h中的部分or全部函数在结构体wpa_driver_ops中注册。wpa_supplicant工作独立于硬件部分,wpa_supplicant将调用这些接口里的函数来控制驱动/无线局域网卡。通过回调函数wpa_supplicant_event()来获取驱动响应的消息。
? driver.h:定义了一系列驱动接口供wpa_supplicant和hostapd使用。文件共分为数据结构、宏定义、枚举、函数四个部分,数据结构用于各种驱动程序操作;函数部分定义了用于驱动事件报告的函数wpa_supplicant_event()和一些方便的辅助函数。
? driver_wext.c & driver_wext.h:实现了wext形式的wpa_driver_ops,并创建了PF_INET socket接口和PF_NETLINK socket接口,然后通过这两个接口完成与kernel的信息交互。
? l2_packet_linux.c:主要用于实现PF_PACKET socket接口,通过该接口,wpa_supplicant可以直接将802.1X packet发送到L2层,而不经过TCP/IP协议栈。
Note:下行接口--wpa_suplicant提供的下行接口主要用于和kernel(driver)进行通信,下发命令和获取信息。主要包括3种接口:
1) PF_INET socket接口:主要用于向kernel发送ioctl命令,控制并获取相应信息。
2) PF_NETLINK socket接口:主要用于接收kernel发送上来的event事件。
3) PF_PACKET socket接口:主要用于向driver传递802.1X报文。
注:对于第五、六点,更多信息请见http://hostap.epitest.fi/wpa_supplicant/devel/index.html
三、流程介绍
从点击打开wifi到wifi开启成功至扫描AP,其流程如下图:
流程框图:
与wpa_supplicant交互:
这是个人学习所写,基于android4.2,若有不正确的地方,请指正,谢谢!
公司代码限制,有些文件不便帖出。