Wifi 连接部分

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

public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {

//点击AP响应函数

if (preference instanceof AccessPoint) {

mSelected = (AccessPoint) preference;

showDialog(mSelected, false);

} else if (preference == mAddNetwork) {

mSelected = null;

showDialog(null, true);

} else if (preference == mNotifyOpenNetworks) {

Secure.putInt(getContentResolver(),

Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,

mNotifyOpenNetworks.isChecked() ? 1 : 0);

} else {

return super.onPreferenceTreeClick(screen, preference);

}

return true;

}

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

public void onClick(DialogInterface dialogInterface, int button) {

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

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

forget(mSelected.networkId);

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

WifiConfiguration config = mDialog.getConfig();

if (config == null) {

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

connect(mSelected.networkId);

}

} else if (config.networkId != -1) {

if (mSelected != null) {

mWifiManager.updateNetwork(config);

saveNetworks();

}

} else {

int networkId = 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, const char *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 维护一个监视线程分发处理底层返回上来的事件

void handleEvent(int event, String remainder) {

switch (event) {

case DISCONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);

break;

case CONNECTED:

handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);

break;

case SCAN_RESULTS:

mWifiStateTracker.notifyScanResultsAvailable();

break;

case UNKNOWN:

break;

}

}

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

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

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

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

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

private void updateConnectionState(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 (int i = 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/

wifi连接流程分析相关推荐

  1. Android 源码 Wi-Fi 连接流程分析

    Wi-Fi 连接过程可以从 Settings App 中点击任意 Wi-Fi 条目连接说起.点击条目以后会弹出一个对话框,根据不同的 Wi-Fi 类型需要填入必要的信息,再点击连接按钮,发起连接过程. ...

  2. Android -- Wifi启动流程分析

    Android -- Wifi启动流程分析 Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了:下面就简单介绍下Android中Wifi的启动流程. 当我在Setting菜单里点击 ...

  3. Android WiFi —softAP流程分析

    Android WiFi - Ap功能实现与源码分析 0. 前言 wifiAp的ip WifiAp的config分析 2.1 默认的config 2.2 修改wifiAp的config配置流程 开启/ ...

  4. android wifi连接流程,(九十三) Android O 连接WiFi AP流程梳理续——保存网络-Go语言中文社区...

    前言: 之前在(五十五)Android O 连接WiFi AP流程梳理 梳理连接流程梳理到SupplicantStaNetworkHal 然后没梳理的下去,现在继续梳理下. 之前梳理的时序图 1.流程 ...

  5. 蓝牙遥控器连接流程分析

    背景 最近在一个Linux系统的ARM板子上移植一款蓝牙芯片,因为我们做的是机顶盒,所以首要功能就是能连接上蓝牙遥控器,并且能正常的接收按键.之前在安卓平台,连接上蓝牙遥控器后,会自动创建/dev/i ...

  6. PD快充协议连接流程分析

    DFP和UFP均会实时监控CC1和CC2引脚的电压,以此来评估DFP和UFP是否都已经在位.同时DFP可以根据电压确定自己所能提供的电流的大小.

  7. Android之wifi工作流程

    Android Wifi的工作流程 一.WIFI工作相关部分 Wifi 网卡状态 1.    WIFI_STATE_DISABLED:WIFI网卡不可用 2.    WIFI_STATE_DISABL ...

  8. Android 中的WiFi学习笔记(转载)----WIFI启动 代码流程走读---网络连接流程

    Android的WiFi 我们通常看到WiFi的守护进程wpa_supplicant在我们的ps的进程列表中,这个就是我们的wifi守护进程.wpa_supplicant在external/wpa_s ...

  9. Android 11 WiFi开启流程

    从刚接触WiFi时跟过wifi的开启流程,当时还是android9.到了Android11代码架构有了不小的改动,在这里重新梳理一遍,便于在工作中更快速的跟踪代码. 一.Settings里改动不大,还 ...

最新文章

  1. H5解码H264实时视频流
  2. 程序员写了段代码,自称完美! 网友: 我现在还在改你的Bug
  3. OpenCV Mat数据类型像素操作
  4. ssm使用全注解实现增删改查案例——Dept
  5. python编写装饰器_我也来写一下python装饰器
  6. Leetcode | Implement strStr()
  7. 信息学奥赛一本通(1189:Pell数列)
  8. Linux中运行c程序,与系统打交道
  9. linux ip onboot,linux onboot no
  10. 每天Leetcode 刷题 初级算法篇-缺失数字
  11. Yann LeCun提出首个多模态高性能自监督算法,语音、图像文本全部SOTA
  12. 电子计算机上total,计算器频幕上grand total 什么意思
  13. uni-app的基本使用
  14. 算法训练营 day20 二叉树 最大二叉树 合并二叉树 二叉搜索树中的搜索 验证二叉树
  15. 在3dmax软件中添加样条的方法和详细步骤
  16. 第十一章 性能与可伸缩性 Java并发编程实战 阅读总结
  17. 【数据库系统原理】数据库课内实验
  18. 建筑业数字化|数据推动建筑业变革与产业升级
  19. 使用GifCam录制程序演示效果图GIF(基于模拟器录制)
  20. xstream异常com.thoughtworks.xstream.security.ForbiddenClassException

热门文章

  1. 四川农业大学计算机专业答辩,四川农业大学远程教育2016年下半年本科论文答辩安排及注意事项...
  2. SOLIDWORKS Simulation Premium中的非线性提示和技巧
  3. 从TCP三次握手说起——浅析TCP协议中的疑难杂症
  4. 游戏服务器修复,服务器内怪物不攻击问题修复方法
  5. 周末出动:广州石室圣心天主教堂
  6. 大数据战略落地实施 上海数据中心交易系统开放
  7. 搭建简单文件和下载服务器的总结
  8. 技术/源码/开源网站
  9. USBoot制作U盘启动盘
  10. 7N60-ASEMI高压MOS管7N60