http://blog.csdn.net/wh_19910525/article/details/7384480
一、wifi 组建原理:
WIFI就是一种无线联网的技术,以前通过网线连接电脑,而现在则是通过无线电波来连网;常见的就是一个无线路由器,那么在这个无线路由器的电波覆盖的有效范围都可以采用WIFI连接方式进行联网,如果无线路由器连接了一条ADSL线路或者别的上网线路,则又被称为“热点”。
一般架设无线网络的基本配备就是 无线网卡 及 一个AP(无线接入点)。有了AP,就像一般有线网络的Hub一般,无线工作站可以快速且轻易地与网络相连。特别是对于宽带的使用,WiFi更显优势,有线宽带网络(ADSL、小区LAN等)到户后,连接到一个AP,然后在电脑中安装一块无线网卡即可上网。普通的家庭有一个AP已经足够,甚至用户的邻里得到授权后,则无需增加端口,也能以共享的方式上网。
二、=================== android WIFI 框架 =======================
---------------------------------------------------------------------------------------------------
三、 Android平台Wifi 编译前 基本代码 路径 及 文件名(根文件系统的源码下)
位于packages/apps/Settings/src/com/android/settings/wifi/
WifiSettings.java&WifiEnabler.java
2、JAVA Framework部分
位于frameworks/base/services/java/com/android/server/
WifiService.java &WifiWatchdogService.java
位于frameworks/base/wifi/java/android/net/wifi/
WifiManager.java&WifiMonitoer.java&WifiStateTracker.java &WifiNative.java
3. Wifi的JNI部分位于 frameworks/base/core/jni/android_net_wifi_Wifi.cpp
4. Wifi的HAL层代码(wpa_supplicant适配器层)
位于 hardware/libhardware_legary/wifi/wifi.c
5. Wpa_supplicant程序的 源码部分(tools)
位于 external/wpa_supplicant_6/
external/wpa_supplicant/
生成库libwpa_client.so 和 守护进程wpa_supplicant
6.kernel (wifi 驱动*.ko)
位于 net/wireless drivers/wlan_sd8688 arch/arm/mach-pxa/wlan_pm.c
四、每一层 编译后 的所在位置
Java应用层
-- Settings, Wifi Switcher等应用
--> /system/app/
Java Framework层
-->
/system/framework/services.jar
JNI层
--> /system/framework/framework.jar
wpa_supplicant 适配器层
--> /system/lib/libhardware_legacy.so
wpa_supplicant 程序
--> /system/bin/wpa_supplicant
/system/lib/libwpa_client.so
Kernel层
-- kernel network drivers
===================== android WIFI 框架 end ====================================
Wifi 网卡状态
1. WIFI_STATE_DISABLED: WIFI网卡不可用
2. WIFI_STATE_DISABLING: WIFI正在关闭
3. WIFI_STATE_ENABLED:WIFI网卡可用
4. WIFI_STATE_ENABLING:WIFI网卡正在打开
5. WIFI_STATE_UNKNOWN:未知网卡状态
Rootfs中 关于wpa_supplicant的配置
1) /device/amlogic/f08refe1/BoardConfig.mk //wpa_supplicant版本,driver
WPA_SUPPLICANT_VERSION := VER_0_6_X
BOARD_WPA_SUPPLICANT_DRIVER := WEXT
2) root/init.rc //wpa_supplicant service
setprop wifi.interface wlan0
service wpa_supplicant /system/bin/wpa_supplicant -Dwext -iwlan0 -d -c /data/misc/wifi/wpa_supplicant.conf
socket wpa_wlan0 dgram 0666 wifi wifi
3) /system/etc/wifi/wpa_supplicant.conf//config for wpa_supplicant service
update_config=1
ctrl_interface=wlan0
eapol_version=1
ap_scan=1
fast_reauth=1
---------------------
http://blog.csdn.net/wh_19910525/article/details/7393589
Wifi模块的初始化:
系统启动 首先加载init.rc,这个文件 会加载所有service,在 SystemServer 启动的时候,会生成一个ConnectivityService 的实例,
try {
Log.i(TAG, "Starting Connectivity Service.");
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, new
ConnectivityService(context));
} catch (Throwable e) {
Log.e(TAG, "Failure starting Connectivity Service", e);
}
ConnectivityService 的构造函数会创建WifiService,
if (DBG) Log.v(TAG, "Starting Wifi Service.");
mWifiStateTracker = new WifiStateTracker(context, handler);
WifiService wifiService = new WifiService(context, mWifiStateTracker);
ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
WifiStateTracker 会创建WifiMonitor 接收来自底层的事件,WifiService 和WifiMonitor 是整
个模块的核心。WifiService 负责启动关闭wpa_supplicant、启动关闭WifiMonitor 监视线程
和把命令下发给wpa_supplicant,而WifiMonitor 则负责从wpa_supplicant 接收事件通知。
具体流程图如下:
一:Wifi模块的启动(使能)
WirelessSettings 在初始化的时候配置了由WifiEnabler 来处理Wifi 按钮,
private void initToggles() {
mWifiEnabler = new WifiEnabler(this,
(WifiManager) getSystemService(WIFI_SERVICE),
(CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI));
当用户按下Wifi 按钮后,Android 会调用WifiEnabler 的onPreferenceChange,再由WifiEnabler
调用WifiManager 的setWifiEnabled 接口函数,通过AIDL,实际调用的是WifiService 的
setWifiEnabled 函数,WifiService 接着向自身发送一条MESSAGE_ENABLE_WIFI 消息,在
处理该消息的代码中做真正的使能工作:首先装载WIFI 内核模块(该模块的位置硬编码为
"/system/lib/modules/wlan.ko" ), 然后启动wpa_supplicant ( 配置文件硬编码为
"/data/misc/wifi/wpa_supplicant.conf"),再通过WifiStateTracker 来启动WifiMonitor 中的监视
线程。
private boolean setWifiEnabledBlocking(boolean enable) {
final int eventualWifiState = enable ? WIFI_STATE_ENABLED :WIFI_STATE_DISABLED;
updateWifiState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING);
if (enable) {
if (!WifiNative.loadDriver()) {
Log.e(TAG, "Failed to load Wi-Fi driver.");
updateWifiState(WIFI_STATE_UNKNOWN);
return false;
}
if (!WifiNative.startSupplicant()) {
WifiNative.unloadDriver();
Log.e(TAG, "Failed to start supplicant daemon.");
updateWifiState(WIFI_STATE_UNKNOWN);
return false;
}
mWifiStateTracker.startEventLoop();
}
// Success!
persistWifiEnabled(enable);
updateWifiState(eventualWifiState);
return true;
}
当使能成功后,会广播发送WIFI_STATE_CHANGED_ACTION 这个Intent 通知外界WIFI
已经成功使能了。WifiEnabler 创建的时候就会向Android 注册接收
WIFI_STATE_CHANGED_ACTION,因此它会收到该Intent,从而开始扫描。
private void handleWifiStateChanged(int wifiState) {
if (wifiState == WIFI_STATE_ENABLED) {
loadConfiguredAccessPoints();
attemptScan();
}
具体流程如下流程图所示:
![](http://hi.csdn.net/attachment/201107/12/0_1310470302WiI4.gif)
![](http://hi.csdn.net/attachment/201107/12/0_1310470591C7U4.gif)
二:查找热点(AP)
上一节(第三部分:Wifi开启)中讲到Wifi模块开启后会对外发送WIFI_STATE_CHANGED_ACTION。WifiLayer中注册了Action的Receiver。
当WifiLayer收到此Action后开始scan的流程,具体如下:
![](http://hi.csdn.net/attachment/201107/12/0_131047040357X7.gif)
![](http://hi.csdn.net/attachment/201107/12/0_1310470701s01w.gif)
三:配置 AP 参数
当用户在 WifiSettings 界面上选择了一个AP 后,会显示配置AP 参数的一个对话框:
![](http://hi.csdn.net/attachment/201107/12/0_1310470730bTI5.gif)
![](http://hi.csdn.net/attachment/201107/12/0_1310470761J9hG.gif)
整个wifi启动 到 使用的流程图:
Wifi驱动模块
厂商提供的source,主要进行load firmware 和 kernel的wireless进行通信;
Wifi电源管理模块
主要控制硬件的GPIO和上下电,让CPU和Wifi模组之间通过sdio接口通信;
http://blog.csdn.net/wh_19910525/article/details/7390189
============================ Wifi 启动代码流程 ====================
1、系统启动 首先加载init.rc,这个文件 会加载所有service,init是linux启动的 第一个 用户空间 的应用(属于linux进程,不属于Android应用)。
2、init.rc里有以下这句话:
Service wpa_supplicant /system/bin/wpa_supplicant –Dwext –iwlan0 –d –c /data/misc/wifi/wpa_supplicant.conf
3、加载linux内核模块/system/lib/modules/wlan.ko 这个wifi模块定义在/hardware/libhardware_legacy/wifi/wifi.c
4、在 SystemServer 启动的时候, 会生成一个 ConnectivityService 的实例 ,
ConnectivityService 的 构造函数 会创建 WifiService,
看看是怎么启动WiFi Service的:
if (DBG) Log.v(TAG, "Starting Wifi Service.");
mWifiStateTracker = new WifiStateTracker(context, handler);
WifiService wifiService = new WifiService(context, mWifiStateTracker);
ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
WifiStateTracker 会创建 WifiMonitor 接收 来自 底层 的事件, WifiService 和 WifiMonitor 是整个模块的核心 。WifiService 负责 启动关闭 wpa_supplicant、启动关闭 WifiMonitor监视线程 和把 命令下发 给 wpa_supplicant, 而WifiMonitor 则负责从 wpa_supplicant 接收 事件通知。它们与本地库的连接都是通过JNI方法,具体实现方法在android_net_wifi_Wifi.cpp中,在这个文件中可以大致看出APP会给wpa_supplicant下哪些命令。这些命令通过wifi.c的wifi_command发送给wpa_supplicant,在发送命令的过程中实际是调用wpa_ctrl_request来完成命令发送的,wpa_ctrl_request是通过socket的方式与wpa_supplicant进行通信的,然后通过wpa_ctrl_recv来接收来自wpa_supplicant的命令,并返回标识给wifi_wait_for_event。
--------------------------------------
流程图对应的源代码路径为:
WifiEnabler,WifiSettings对应的路径如下:
rootfs/packages/apps/Settings/src/com/android/settings/wifi/
WifiManager,WifiMonitor,WifiStateTracker,WifiNative.对应的源代码路径如下:
rootfs/frameworrks/base/wifi/java/android/net/wifi/
WifiService 对应代码的位置
rootfs/frameworks/base/services/java/com/android/server/
android_net_wifi_Wifi源代码路径如下:
rootfs/frameworks/base/core/jni/
wifi_command,wifi_wait_for_envent源代码路径如下:
/hardware/libhardware_legacy/wifi/wifi.c
wpa_ctrl_源代码路径如下:
rootfs/external/wpa_supplicant/wpa_ctrl.c
wpa_supplicant源代码路径如下:
rootfs/external/wpa_supplicant/
WIFI启动流程图:
Wireless Settings 在初始化的时候配置了由 WifiEnabler 来处理 Wifi 按钮, 当用户按下 Wifi 按钮后, Android 会调用 WifiEnabler 的 onPreferenceChange, 再由 WifiEnabler 调用 WifiManager 的 setWifiEnabled 接口 函数,通过 AIDL,实际调用的是 WifiService 的 setWifiEnabled 函数, WifiService 接着向自身发送一条 MESSAGE_ENABLE_WIFI 消息, 在 处理该消息的代码 中做真正的使能工作: 首先装载 WIFI 内核模块(该模块的位置为 "/system/lib/modules/wlan.ko" ),然后启动 wpa_supplicant ( 配置文件 为"/data/misc/wifi/wpa_supplicant.conf") ,再通过 WifiStateTracker 来启动 WifiMonitor 中的 监视线程。
代码如下:
WifiService.java (frameworks/base/services/java/com/android/server)调用 setWifiEnabled()里面的sendEnableMessage(enable, true, Binder.getCallingUid());来发送一则消息
Message msg = Message.obtain(mWifiHandler, (enable? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),(persist ? 1 : 0), uid);
msg.sendToTarget();发送给自身的消息。
当enable 的时候 会调用setWifiEnabledBlocking这个函数,这个函数会做setWifiEnabledState ,然后做四件事:
1. 调用JNI的WifiNative.loadDriver -->加载 Wifi驱动
2. 调用JNI的WifiNative.startSupplicant -->启动wifi_start_supplicant
3. 启动 event loop.
4. 更新wifi的状态
成功启动wifi之后 setWifiEnabledBlocking 运行mWifiStateTracker.startEventLoop();事件循环,来监视事件mWifiMonitor.startMonitoring(); MonitorThread().start() 一直在线程里循环调用WifiNative.waitForEvent();
当 使能 成功后, 会广播发送 WIFI_STATE_CHANGED_ACTION 这个 Intent 通知外界 WIFI已 经 成功能了。WifiEnabler创 建 的 时 候 就 会 向 Android 注册 接收WIFI_STATE_CHANGED_ACTION, 因此它会收到该 Intent, 从而开始扫描。
二、 查找 AP
扫描的入口函数是 WifiService 的 startScan, 它其实也就是 往 wpa_supplicant 发送 SCAN 命令。
当 wpa_supplicant 处理完 SCAN 命令后, 它会向 控制通道 发送 事件 通知 扫描完成, 从而 wifi_wait_for_event函数会接收到该事件, 由此 WifiMonitor 中的 MonitorThread 会被执行来 处理 这个事件。对每一个扫描返回的 AP, WifiLayer 会调用 WifiSettings 的 onAccessPointSetChanged 函数, 从而最终把该 AP 加到 GUI 显示列表中。
三、配置 AP 参数
当用户在 WifiSettings 界面上选择了一个 AP 后,会显示配置 AP 参数的一个对话框,此对话框会显示当前选择的AP信号强度,若此AP设置了密码则需要用户输入密码才能登录。用户配置好之后,点击 连接按钮,onClick函数会被调用。
四、连接
当用户在 AcessPointDialog 中 选择好 加密方式 和 输入密钥 之后,再点击 连接按钮, Android就会去连接这个 AP。
WifiLayer 会先检测这个 AP 是不是之前被配置过, 这个是通过 向 wpa_supplicant 发送 LIST_NETWORK 命令 并且比较 返回值 来实现的,
// Need WifiConfiguration for the AP
WifiConfiguration config = findConfiguredNetwork(state);
如果 wpa_supplicant 没有这个 AP 的配置信息, 则会向 wpa_supplicant 发送 ADD_NETWORK 命令来添加该 AP,
if (config == null)
{
// Connecting for the first time, need to create it
config = addConfiguration(state, ADD_CONFIGURATION_ENABLE|ADD_CONFIGURATION_SAVE);
}
ADD_NETWORK 命令 会返回一个 ID , WifiLayer 再用这个返回的 ID 作为 参数 向wpa_supplicant 发送 ENABLE_NETWORK 命令,从而让 wpa_supplicant 去连接该 AP。
五、配置 IP 地址
当 wpa_supplicant 成功连接上 AP 之后, 它会向 控制通道 发送 事件通知连接上 AP 了,
wifi.c的wifi_wait_for_event函数阻塞调用,从而 wifi_wait_for_event 函数会 接收 到该事件,由此 WifiMonitor 中的 MonitorThread 会被执行来 处理 这个事件, WifiMonitor 再调用 WifiStateTracker 的 notifyStateChange, WifiStateTracker 则接着会往自身发送 EVENT_DHCP_START 消息 来 启动 DHCP 去获取 IP 地址, 然后再广播发送NETWORK_STATE_CHANGED_ACTION 这个 Intent, 最后由 WifiSettings类来响应,改变状态和界面信息。
注意:wpa_ctrl_request,通过socket方式向wpa_supplicant发送命令,以select模式阻塞在wpa_supplicant发送和接收。