文档章节

wifi连接流程分析

t
 tonytony
发布于 2014/12/08 14:54
字数 1601
阅读 78
收藏 0

       wifi连接流程分析            

       分类:            Android            2012-03-31 16:02    486人阅读    评论(0)    收藏    举报    

network网络nullcommandactionandroid

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';

    /* LOGD("wait_for_event: result=%d nread=%d string=/"%s/"/n", result, nread, buf); */

    /* Check for EOF on the socket */

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

        /* Fabricate an event to pass up */

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

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

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

        return strlen(buf);

    }

    /*

     * Events strings are in the format

     *

     *     <N>CTRL-EVENT-XXX

     *

     * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,

     * etc.) and XXX is the event name. The level information is not useful

     * to us, so strip it off.

     */

    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] =='<') {

                                     /* This is an unsolicited message from

                                      * wpa_supplicant, not the reply to the

                                      * request. Use msg_cb to report this to the

                                      * caller. */

                                     if (msg_cb) {

                                               /* Make sure the message is nul

                                                * terminated. */

                                               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

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

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

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

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

  

   privatevoidupdateConnectionState(DetailedStatestate){

        /* sticky broadcasts can call this when wifi is disabled */

        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/


本文转载自: http://blog.csdn.net/typename/article/details/5879121

t
粉丝 2
博文 31
码字总数 12345
作品 0
合肥
私信 提问
Android 7.0 WifiMonitor工作流程分析

在wifi启动扫描的分析过程中,出现了多次WifiMonitor的操作,在此分析一下这个函数是如何工作的。 在Android的Wifi体系中,WifiMonitor承担着分发来自wpasupplicant底层事件的任务。当上层下...

天王盖地虎626
06/03
15
0
android -------- WIFI 详解

今天简单的来聊一下安卓开发中的Wifi,一些常用的基础,主要分为两部分: 1:WiFi的信息 2:WiFi的搜索和连接 现在app大多都需要从网络上获得数据。所以访问网络是在所难免。但是在访问网络之...

切切歆语
2018/04/18
45
0
Android wifi源码分析(二) Wifi关闭流程

接着上一篇,这篇说一下Wifi的关闭流程。 由上一篇可以知道,framework层提供的wifi开关接口都是setWifiEnabled,只是参数不同而已。true表示开启wifi、false表示关闭wifi。 Wifi开关在WifiM...

VNanyesheshou
2017/09/16
0
0
Android wifi源码分析(一) Wifi启动流程

最近在解决wifi的一些问题,故研究下wifi源码。 该源码是基于Android4.3,其他版本略有改动,大致流程一样。 这篇主要说一下wifi的启动流程。 WifiManager 先从wifi的开启来看,WifiManager中...

VNanyesheshou
2017/09/06
0
0
Android WiFi--系统架构

系统架构 Android WiFi系统引入了wpasupplicant,它的整个WiFi系统以wpasupplicant为核心来定义上层用户接口和下层驱动接口。整个WiFi系统架构如下图所示: 一切尽在上图中,下面将对每部分进...

sflfqx
2014/04/10
435
0

没有更多内容

加载失败,请刷新页面

加载更多

安全组和云防火墙的区别

前言 熟悉云平台的朋友可能都会注意到这样一个事情:无论公有云还是私有云,创建虚拟机的时候都需要选择安全组,来对虚拟机进行安全防护;有的云平台在VPC里,还能选择防火墙,ZStack在3.6版...

ZStack社区版
30分钟前
2
0
教育性app开发的重要性和好处

在这个精通技术的世界中,流行的app主导着无聊的教育系统。当我们将技术和教育结合在一起时,它将带来当代以及强大的学习资源。因此,将教育移动app集成到您的学习过程中,并根据自己的信念把...

a429011717
31分钟前
3
0
IE6/7/8如何兼容CSS3属性

本文转载于:专业的前端网站➩IE6/7/8如何兼容CSS3属性 最近在工作中总是要求IE8兼容CSS3属性,在网上搜了搜主要是引入了一个htc文件(ie-css3.htc或者PIE.htc。个人认为这两个文件的作用差不...

前端老手
46分钟前
4
0
手把手教你ALLEGRO的约束规则的设置教程!

约束规则的设置 分三步, 定义规则(一、基本约束规则设置:1、线间距设置;2、线宽设置;3、设置过孔;4、区域约束规则设置;5、设置阻抗;6、设置走线的长度范围;7、设置等长:7.1、不过电阻的NET 等...

demyar
48分钟前
5
0
完美解决H5滚动滑动穿透方案:不使用系统滚动

网上有很多黑科技解决这个问题,都不是从根本去解决,例如通过js控制弹出时html加上position:fixed; 弹窗关闭后再去掉该样式,总觉得不太对,像是打补丁。 今天终于找到了滚动穿透的原因和完...

未来cc
52分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部