您的位置:首页 > 其它

wifi连接流程分析

2013-12-19 20:54 323 查看
Wifi 连接部分



当用户选择一个AP时会弹出一个AP参数配置对话框,此对话框会显示当前选择的AP信号强度,若此AP设置了密码则需要用户输入密码才能登录。WifiSettings中的onPreferenceTreeClick会被调用 @Override

publicbooleanonPreferenceTreeClick(PreferenceScreenscreen,Preferencepreference){

//点击AP响应函数

if(preferenceinstanceofAccessPoint){

mSelected=(AccessPoint)preference;

showDialog(mSelected,false);

}elseif(preference==mAddNetwork){

mSelected=null;

showDialog(null,true);

}elseif(preference==mNotifyOpenNetworks){

Secure.putInt(getContentResolver(),

Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,

mNotifyOpenNetworks.isChecked()?1:0);

}else{

returnsuper.onPreferenceTreeClick(screen,preference);

}

returntrue;

}

用户配置好之后点击连接按钮,onClick函数会被调用。

publicvoidonClick(DialogInterfacedialogInterface,intbutton){

//点击连接按钮的响应函数

if(button==WifiDialog.BUTTON_FORGET&&mSelected!=null){

forget(mSelected.networkId);

}elseif(button==WifiDialog.BUTTON_SUBMIT&&mDialog!=null){

WifiConfigurationconfig=mDialog.getConfig();

if(config==null){

if(mSelected!=null&&!requireKeyStore(mSelected.getConfig())){

connect(mSelected.networkId);

}

}elseif(config.networkId!=-1){

if(mSelected!=null){

mWifiManager.updateNetwork(config);

saveNetworks();

}

}else{

intnetworkId=mWifiManager.addNetwork(config);

if(networkId!=-1){

mWifiManager.enableNetwork(networkId,false);

config.networkId=networkId;

if(mDialog.edit||requireKeyStore(config)){

saveNetworks();

}else{

connect(networkId);

}

}

}

}

连接请求部分

一.Settings的connect函数响应连接,更新网络保存配置,更新设置当前选择的优先级最高,并

保存。然后通过enableNetwork使得其他网络不可用来进行连接。最后调用WifiManager的

reconnect函数连接当前选择的网络。

二.WifiManager的reconnect函数通过AIDL的Binder机制,调用WifiService的reconnect函数

三.然后会调用
WifiStateTracker的reconnectCommand函数,通过JNI(android_net_wifi_Wifi)的

android_net_wifi_reconnectCommand
函数向WPA_WPASUPPLICANT发送 RECONNECT命令。

四.
android_net_wifi_Wifi通过doCommand(命令名,响应缓冲,响应缓存大小)调用wifi.c中的

wifi_command函数来发送命令。

五.最后通过 wpa_ctrl的wpa_ctrl_request函数向控制通道发送连接命令。

返回请求部分

六.当连接上之后WPA_SUPPLICANT会向控制通道发送连接成功命令。wifi.c的

wifi_wait_for_event函数阻塞调用并返回这个命令的字符串(CONNECTED).

七.而后WifiMonitor会被执行来处理这个事件,WifiMonitor 再调用 WifiStateTracker的

notifyStateChange,WifiStateTracker
则接着会往自身发送 EVENT_DHCP_START 消息来启动

DHCP
去获取 IP 地址,然后广播NETWORK_STATE_CHANGED_ACTION消息,最后由

WifiSettings类来响应,改变状态和界面信息。

关键函数功能介绍

一.connect函数功能

1.updateNetwork:updateNetwork(config)会将当前选择连接的AP配置信息

信息传递进去,配置信息有(网络ID等)。如果网络ID为-1则重新添加网络配置,然后向

wpa_supplicant 发送SET_NETWORK命令(即通过这个网络ID设置其他一些相关信息,设置

SSID,密码等)如果网络配置不为-1则直接执行后面步骤即发送SET_NETWORK命令。

2.saveNetwork:告诉supplicant保存当前网络配置并更新列表。SaveNetwork会调用WifiService的

saveConfiguration向wpa_supplicant发送SAVE_CONFIG命令保存当前网络配置信息,

如果返回false,则向wpa_supplicant重新发送RECONFIGURE命令获取配置信息,如果获取信

息成功后,会Intent一NETWORK_IDS_CHANGED_ACTION事件WifiSettings会注册接受

这个
时间并更新列表。

3.enableNetwork函数,向系统获取接口名并使得该接口有效。由于之前传递的disableOthers

为true则向wpa_supplicant发送SELECT_NETWORK(如果传递的为false则发送

ENABLE_NETWORK命令),

4.reconnect函数:连接AP

二.reconnect函数功能:connect函数会调用WifiManager的reconnect然后通过Binder机制调用

WifiService的reconnect,再由WifiStateTracke调用WifiNative向wpa_supplicant发送

RECONNECT命令去连接网络,当连接上wpa_supplicant之后会向控制通道发送连接成功的命

令,

wifi_wait_for_event函数阻塞等待该事件的发生,并返回这个命令的字符串(CONNECTED)

三.android_net_wifi_Wifi函数的doCommand函数会调用wifi.c的wifi_command函数将上层的命

令向wpa_supplicant发送。

四.wifi_wait_for_event函数以阻塞的方式,等待控制通道传递的事件。当有事件传递过来的时候

该函数会通过wpa_ctrl的wpa_ctrl_recv函数读取该事件,并以字符串形式返回该事件名。

int wifi_wait_for_event(char *buf,
size_t buflen)

{

.......

result
= wpa_ctrl_recv(monitor_conn, buf, &nread);

if (result
< 0) {

LOGD("wpa_ctrl_recv
failed: %s/n",
strerror(errno));

strncpy(buf,
WPA_EVENT_TERMINATING " - recv error", buflen-1);

buf[buflen-1]
= '/0';

return strlen(buf);

}

buf[nread]
= '/0';

if (result
== 0 && nread == 0) {

LOGD("Received
EOF on supplicant socket/n");

strncpy(buf,
WPA_EVENT_TERMINATING " - signal 0 received", buflen-1);

buf[buflen-1]
= '/0';

return strlen(buf);

}

if (buf[0]
== '<') {

char *match
= strchr(buf, '>');

if (match
!= NULL) {

nread
-= (match+1-buf);

memmove(buf,
match+1, nread+1);

}

}

return nread;

}

五.wpa_ctrl_request,通过socket方式向wpa_supplicant发送命令,以select模式阻塞在

wpa_supplicant发送和接收。

int wpa_ctrl_request(struct wpa_ctrl
*ctrl, constchar *cmd, size_t
cmd_len,char *reply, size_t
*reply_len,void(*msg_cb)(char *msg, size_t len))

{

.......

res
= select(ctrl->s + 1, &rfds, NULL, NULL, &tv);

if (FD_ISSET(ctrl->s,
&rfds)) {

res
= recv(ctrl->s, reply, *reply_len, 0);

if (res
< 0)

return res;

if (res
> 0 && reply[0] == '<') {

if (msg_cb)
{

if ((size_t)
res == *reply_len)

res
= (*reply_len) - 1;

reply[res]
= '/0';

msg_cb(reply,
res);

}

continue;

}

*reply_len
= res;

break;

} else {

return -2;

}

}

return 0;

}

六.WifiMonitor
维护一个监视线程分发处理底层返回上来的事件

voidhandleEvent(intevent,Stringremainder){

switch(event){

caseDISCONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED,remainder);

break;

caseCONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder);

break;

caseSCAN_RESULTS:

mWifiStateTracker.notifyScanResultsAvailable();

break;

caseUNKNOWN:

break;

}

}

此时返回的事件是CONNECTED因此 handleNetworkStateChange会被调用,验证一下BSSID,重新获得networkId

,然后调用WifiStateTracke的notifyStateChange通知状态改变了的消息(EVENT_NETWORK_STATE_CHANGED)

接着处理这个消息,会移除可用网络通告,然后通过configureInterface()的动态获取IP地址。最后

发送一个NETWORK_STATE_CHANGED_ACTION
Intent,WifiSetings注册了此Intent因此会响应该它。由updateConnectionState函数响应。

七.updateConnectionState 获取连接信息,更新列表状态,设置为Connected,然后设置当前网络为可用状态

privatevoidupdateConnectionState(DetailedStatestate){

if(!mWifiManager.isWifiEnabled()){

mScanner.pause();

return;

}

if(state==DetailedState.OBTAINING_IPADDR){

mScanner.pause();

}else{

mScanner.resume();

}

mLastInfo=mWifiManager.getConnectionInfo();

if(state!=null){

mLastState=state;

}

for(inti=mAccessPoints.getPreferenceCount()-1;i>=0;--i){

((AccessPoint)mAccessPoints.getPreference(i)).update(mLastInfo,mLastState);

}

if(mResetNetworks&&(state==DetailedState.CONNECTED||

state==DetailedState.DISCONNECTED||state==DetailedState.FAILED)){

updateAccessPoints();

enableNetworks();

}

}

流程图对应的源代码路径为:

WifiEnabler,WifiSettings对应的路径如下:

froyo/packages/apps/Settings/src/com/android/settings/

WifiManager,WifiMonitor,WifiStateTracker,WifiNative.对应的源代码路径如下:

froyo/frameworrks/base/wifi/java/android/net/wifi/

WifiService对应代码的位置

froyo/frameworks/base/services/java/com/android/server/

android_net_wifi_Wifi源代码路径如下:

froyo/frameworks/base/core/jni/

wifi_command,wifi_wait_for_envent源代码路径如下:

/hardware/libhardware_legacy/wifi/wifi.c

wpa_ctrl_源代码路径如下:

/external/wpa_supplicant/wpa_ctrl.c

wpa_supplicant源代码路径如下:

froyo/external/wpa_supplicant/

From : /article/1570788.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: