Android WiFi 架构总览(模块及接口)
https://blog.csdn.net/xusiwei1236/article/details/48495485
systemServer.java
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
|
|_____
public WifiService(Context context) {
super(context);
mImpl = new WifiServiceImpl(context);
}
|
|
—— mWifiStateMachine = new WifiStateMachine(mContext, mFacade,
|
|
|-------mWifiNative = WifiNative.getWlanNativeInterface();
-------------------------------------------------------------------------------------------
WifiNative
从功能上来说, wifiNative 是system_server和wpa_supplicant 对话的窗口,实际
主要依靠wpa_supplicnat 项目编译出来的动态库libwpa_client.so
frameworks/base/core/jni/android_net_wifi_WifiNative.cpp
WifiNative的native方法的实现:
static JNINativeMethod gWifiMethods[] = {
/* name, signature, funcPtr */
{ "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },
{ "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded },
{ "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver },
{ "startSupplicant", "(ZI)Z", (void *)android_net_wifi_startSupplicant },
{ "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant },
{ "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant },
{ "closeSupplicantConnectionNative", "()V", (void *)android_net_wifi_closeSupplicantConnection },
{ "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent },
{ "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand },
{ "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand },
{ "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand },
{ "setMaxTxPower", "(IZ)Z", (void *)android_net_wifi_setMaxTxPower },
};
--------------------------------------------------------------------------------------------
WIFI HAL
实现SystemServer 与wpa_supplicant(hostap) 通信的,即WIFI HAL
wifi Hal 封装Unix域socket, SystemServer 通过Unix域socket
与wpa_supplicant(hostapd)
通信; Systemserver 发送的消息和wpa_supplicant 响应的消息都是ASCII 字符串;
wifi HAL 代码主要分布在:
hardware/libhardware_legacy/wifi
hardware/qcom/wlan/libmaxtxpower
——————————————————————————————————————————————————————————————————————————————————————————
wpa_supplicant(hostapd)
代码位于:
external/wpa_supplicant_8
该项目包含两个互相相关的开源项目 wpa_supplicant 和hostapd,
他们将生成两个可执行文件 wpa_supplicant 和hostapd, 分别为STA 模式
和AP模式是的守护进程。
除此之外,还会生成用于测试的wpa_cli, hostapd_cli,
以及WIFI HAL 依赖的wpa_client.so,具体可以到Android.mk 中找到。
wpa_supplicant 源码结构和hostapd 类似, 下面只介绍wpa_supplicant.
wpa_ctrl.h 定义了与wpa_supplicant( 或hostapd) 进程通信的接口:
strcut wpa_ctrl* wpa_ctrl_open( const char* ctrl_path)
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
// Close a control interface to wpa_supplicant/hostapd
void wpa_ctrl_close(struct wpa_ctrl *ctrl);
// Send a command to wpa_supplicant/hostapd
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len));
// Register as an event monitor for the control interface
int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
// Unregister event monitor from the control interface
int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
// Receive a pending control interface message
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
// Check whether there are pending event messages
int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
// Get file descriptor used by the control interface
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
wpa_ctrl_open 创建一个UNIX域socket 与 wpa_supplicant (或者hostapd)进程
相连,
wpa_ctrl_close 用于关闭wpa_ctrl_open 创建的连接,
wpa_ctrl_request 用于wpa_supplicant/hostapd 发送控制struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
// Close a control interface to wpa_supplicant/hostapd
void wpa_ctrl_close(struct wpa_ctrl *ctrl);
// Send a command to wpa_supplicant/hostapd
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len));
// Register as an event monitor for the control interface
int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
// Unregister event monitor from the control interface
int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
// Receive a pending control interface message
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
// Check whether there are pending event messages
int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
// Get file descriptor used by the control interface
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
wpa_supplicant 与内核通信
wpa_supplicant 的运行模型是单进程单线程的Reactor(IO multiplexing)
wpa_supplicant 通过NETLINK socket与内核通信。
wpa_supplicant 项目支持多种驱动编程接口, 在
Android 上使用是nl80211;
nl80211是最新的802.11netlink接头公共头,
与cfg80211 一同组成了wireless-Extensions的替代方案。
cfg80211 是Linux 802.11配置API, nl80211设备,同时用于内核到用户空间的通信。
wireless module(in kernel)
代码位于 kernel/net/wireless
nl80211.c 的nl80211_init 使用genl_register_family_with_ops 注册了
响应应用程序的 struct genl_ops nl80211_ops[],
该数组定义了响应NETLINK 消息的函数。
scan 扫描过程:
APP:setting
WifiManager wifiManager = (WifiManager)Context.getService(Contex.WIFI_SERVICE);
wifiManager.startScan();
//wifiManager --> IWifiManager.Stub.Proxy
IWifiManager.Stub.Proxy implements android.net.wifi.IWifiManager
wifiManager.startScan()
-> IWifiManager.Stub.Proxy.startScan(WorkSource=null);
-> BinderProxy.transact(Stub.TRANSACTION_startScan, _data, _reply, 0)
/////////////////////////////
|
|
|—————framewrok-----------------------------------
wifiManager.startScan()
|
|_
mWifiStateMachine.startScan(Binder.getCallingUid(), scanRequestCounter++,
settings, workSource);
|
|_
sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle);
|
|
case CMD_START_SCAN:
handleScanRequest(message);
|
|_
if (startScanNative(freqs, hiddenNetworkIds, workSource))
|
|
WifiNative.scan(type, freqs)
|
|_
return doBooleanCommand(scanCommand.toString());
|
|_doBooleanCommandNative
|
--------native/JNI------------ -------
|_
static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
|
|
doCommand(env, javaCommand, reply, sizeof(reply))
|
|
_____________hardware_________________
_::wifi_command(command.c_str(), reply, &reply_len) != 0
|
|_
wifi_send_command(command, reply, reply_len)
|
-----------wpa_supplicnat__________________
|_ wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
//注册socket read 函数
|
eloop_register_read_sock(priv->sock, |
wpa_supplicant_global_ctrl_iface_receive, |
global, priv); |
|
|_ wpa_supplicant_global_ctrl_iface_receive
|
|
|_wpa_supplicant_global_ctrl_iface_process
|
|
|
//dispatch cmd 命令
|
if (os_strcmp(buf, "ATTACH") == 0) { |
if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst, &from, //连接 |
fromlen, 1)) |
reply_len = 1; |
else |
reply_len = 2; |
} else if (os_strcmp(buf, "DETACH") == 0) { //断开 |
if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst, &from, |
fromlen)) |
reply_len = 1; |
else |
reply_len = 2; |
} else { |
reply_buf = wpa_supplicant_global_ctrl_iface_process( //scan 或者其他命令 |
global, buf, &reply_len); |_
} else if (os_strcmp(buf, "SCAN") == 0) {
wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
|
|
void wpa_supplicant_event(void *ctx, enum wpa_event_type event, |
union wpa_event_data *data)
|___wpa_supplicant_scan
resched = wpa_s->scanning && wpas_scan_scheduled(wpa_s); |
|
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
|
|
/** |
* wpa_supplicant_trigger_scan - Request driver to start a scan |
* @wpa_s: Pointer to wpa_supplicant data |
* @params: Scan parameters |
* Returns: 0 on success, -1 on failure
|
radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
|
|
—wpas_trigger_scan_cb
|
|
_wpa_drv_scan
|
|
return wpa_s->driver->scan2(wpa_s->drv_priv, params);
|
|
_driver_nl80211_scan2
|
|
_wpa_driver_nl80211_scan
|
process_global_event
|
static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
_nl80211_scan_common
NL80211_CMD_TRIGGER_SCAN |
---------------kernel/net/wireless/nl80211.c:9053 |
// ... ...
{
.cmd = NL80211_CMD_TRIGGER_SCAN,
.doit = nl80211_trigger_scan,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
// ... ...
};
转载 https://blog.csdn.net/lansefeiyang08/article/details/43703315