Android WiFi 架构总览(模块及接口)

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,            
                                                                                                                 },                                               
                                                                                                             // ... ...                                           
                                                                                                             };

                                        




Android WiFi 架构总览(模块及接口)_第1张图片Android WiFi 架构总览(模块及接口)_第2张图片

  转载 https://blog.csdn.net/lansefeiyang08/article/details/43703315 
                                    

你可能感兴趣的:(android,wifi,android内核)