wifi 链接流程

WIFI连接流程

分类:Android2011-07-2110:55268人阅读评论(0)收藏举报

Wifi 连接部分

 

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

    publicbooleanonPreferenceTreeClick(PreferenceScreen screen, Preference preference){

        //点击AP响应函数

        if(preference instanceofAccessPoint) {

           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函数会被调用。

public voidonClick(DialogInterface dialogInterface, intbutton) {

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

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

           forget(mSelected.networkId);

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

           WifiConfiguration config =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);

                   }

               }

           }

        }

 

连接请求部分

.Settingsconnect函数响应连接,更新网络保存配置,更新设置当前选择的优先级最高,并保存。然后通过enableNetwork使得其他网络不可用来进行连接。最后调用WifiManagerreconnect函数连接当前选择的网络。

.WifiManagerreconnect函数通过AIDLBinder机制,调用WifiServicereconnect函数

.然后会调用WifiStateTrackerreconnectCommand函数,通过JNIandroid_net_wifi_Wifi)android_net_wifi_reconnectCommand函数向WPA_WPASUPPLICANT发送RECONNECT命令。

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

     wifi_command函数来发送命令。

.最后通过wpa_ctrlwpa_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.updateNetworkupdateNetwork(config)会将当前选择连接的AP配置信息

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

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

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

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

    saveConfigurationwpa_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函数会调用WifiManagerreconnect然后通过Binder机制调用

  WifiServicereconnect,再由WifiStateTracke调用WifiNativewpa_supplicant发送

  RECONNECT命令去连接网络,当连接上wpa_supplicant之后会向控制通道发送连接成功的命令,wifi_wait_for_event函数阻塞等待该事件的发生,并返回这个命令的字符串(CONNECTED

.android_net_wifi_Wifi函数的doCommand函数会调用wifi.cwifi_command函数将上层的命令向wpa_supplicant发送。

.wifi_wait_for_event函数以阻塞的方式,等待控制通道传递的事件。当有事件传递过来的时候该函数会通过wpa_ctrlwpa_ctrl_recv函数读取该事件,并以字符串形式返回该事件名。

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

       returnstrlen(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 supplicantsocket/n");

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

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

       returnstrlen(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);

        }

    }

    returnnread;

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

   wpa_supplicant发送和接收。

intwpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_tcmd_lenchar*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)

                                    returnres;

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

                                    /* This is an unsolicited message from

                                     * wpa_supplicant, not the reply tothe

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

                  }

        }

        return0;

}

 

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

 voidhandleEvent(intevent, String remainder) {

           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_ACTIONIntentWifiSetings注册了此Intent因此会响应该它。由updateConnectionState函数响应。

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

   privatevoidupdateConnectionState(DetailedState state) {

        /*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/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android的WiFi连接流程图主要包括以下步骤: 1. 打开WiFi:用户进入设置界面,打开设备的WiFi开关,使设备开始搜索可用的WiFi网络。 2. 搜索和扫描:Android设备开始搜索周围的WiFi网络,扫描到的网络信息将会显示在WiFi设置列表中,包括网络名称(SSID)、信号强度等。 3. 用户选择网络:用户根据列表中显示的网络信息,选择要连接的WiFi网络。 4. 请求连接:Android设备通过向选择的WiFi网络发送请求连接的请求,包括认证信息和其他必要的参数。 5. 连接认证:WiFi网络收到连接请求后,会进行身份验证,包括密码验证、MAC地址过滤等。如果认证通过,网络将发送认可的连接响应。 6. IP地址获取:一旦连接成功,Android设备将向WiFi网络请求分配一个IP地址,以便在网络上进行通信。 7. 地址分配:WiFi网络会为设备分配一个合法的IP地址,并将该信息通过DHCP(动态主机配置协议)返回给设备。 8. 连接成功:设备接收到IP地址和其他网络配置信息后,与WiFi网络建立连接成功。 9. 数据传输:现在,设备可以通过WiFi网络进行数据传输,包括浏览互联网、收发电子邮件等。 10. 断开连接:当用户关闭设备的WiFi开关或者设备离开WiFi网络的范围时,设备会与WiFi网络断开连接。 总的来说,Android的WiFi连接流程图涵盖了搜索、选择、连接认证、IP地址获取、数据传输等多个环节,确保设备可以顺利地连接和使用WiFi网络。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值