系统启动后的 wifi 加载过程

来源:互联网 发布:python 字符串 函数 编辑:程序博客网 时间:2024/04/18 22:16

============================ Wifi 启动代码流程 ====================


1、系统启动 首先加载init.rc,这个文件 会加载所有serviceinit是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启动流程图:


一、 使能 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发送和接收。




原创粉丝点击