前文回顾
前言
- 基于Android P源码学习;
- 代码片为了方便阅读段经过删、裁减,请以实际源码为准;
入口
根据前两篇的分析结果,调用栈都汇聚到了WifiNative:
打开Wifi:
mWifiNative.setupInterfaceForClientMode(false, mWifiNativeInterfaceCallback)
关闭Wifi:
mWifiNative.teardownInterface(mClientInterfaceName);
因此我们从WifiNative开始;
照例,我仍以“打开Wifi”为例分析(后续会补上“关闭Wifi”的部分,但仅会重点介绍差异部分)
WifiNative
初始化
构造方法只有一个:
public WifiNative(WifiVendorHal vendorHal,
SupplicantStaIfaceHal staIfaceHal, HostapdHal hostapdHal,
WificondControl condControl, WifiMonitor wifiMonitor,
INetworkManagementService nwService,
PropertyService propertyService, WifiMetrics wifiMetrics,
Handler handler) {...}
构造WifiNative对象的地方依旧是WifiInjector:
mWifiNative = new WifiNative(
mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWificondControl,
mWifiMonitor, mNwManagementService, mPropertyService, mWifiMetrics,
new Handler(mWifiStateMachineHandlerThread.getLooper()));
这里参数很多,需要逐一介绍下,以便于后续深入HAL的分析:
-
WifiVendorHal
:mWifiVendorHal
- 与
android.hardware.wifi@1.0
的HAL实现服务交互的工具类;
- 与
-
SupplicantStaIfaceHal
:mSupplicantStaIfaceHal
- 与
android.hardware.wifi.supplicant@1.0
的HAL实现服务交互的工具类; - 与vendor自定义的,有相关功能的HAL交互,例如
vendor.qti.hardware.wifi.supplicant@2.0
- 与
-
HostapdHal
:mHostapdHal
- 与
android.hardware.wifi.hostapd@1.0
的HAL实现服务交互的工具类; - 与vendor自定义的,有相关功能的HAL交互,例如
vendor.qti.hardware.wifi.hostapd@1.0
- 与
-
WificondControl
:mWificondControl
- 负责通过Binder与
wificond
进程交互(IWificond
)
- 负责通过Binder与
-
WifiMonitor mWifiMonitor
- 一个负责收集、分发wpa_supplicant状态的工具类;
-
INetworkManagementService
:mNwManagementService
INetworkManagementService
实现类的的客户端实例
-
PropertyService
:mPropertyService
- 类型为
PropertyService
的接口,实现类型为SystemPropertyService
,本质是对android.os.SystemProperties
的get
/set
方法进行非静态封装;
- 类型为
-
WifiMetrics
:mWifiMetrics
- 用于记录WIFI行为,包括连接、断开事件,已保存网络个数,开放网络个数等的业务类;
-
Handler
:new Handler(mWifiStateMachineHandlerThread.getLooper())
- 用于处理异步消息的
Handler
- 用于处理异步消息的
由此可见,负责与HAL交互的,更多是前面4个参数:mWifiVendorHal
,mSupplicantStaIfaceHal
,mHostapdHal
,mWificondControl
;
关于这些模块的详细分析计划在后期再更新,当前仅着眼于开、关WIFI调用栈的HAL部分;
打开WIFI
即:setupInterfaceForClientMode()
:
public String setupInterfaceForClientMode(boolean lowPrioritySta,
@NonNull InterfaceCallback interfaceCallback) {
synchronized (mLock) {
...
/*
* mIfaceMgr为IfaceManager的实例对象,内部维护了一个HashMap<Integer, Iface>,
* 用于管理Iface的增、删、查等操作;
* allocateIface方法即为上述的“增”。
* 但是需要注意,这里的“增”只是Framework层面的构造了一个Iface对象并添加到HashMap
* 中,并没有发送请求到HAL去真正创建一个Iface。
*/
Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
...
iface.externalListener = interfaceCallback;
/*
* 创建Iface名称,如果Vendor HAL不存在,则取属性"wifi.interface"
* 如果属性没设置,返回"wlan0"
*/
iface.name = createStaIface(iface, lowPrioritySta);
...
/*
* 通知wificond调用createClientInterface创建iface,返回类型为IClientInterface
* 的实例对象;
*/
if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
teardownInterface(iface.name);
return null;
}
/*
* 根据不同的wpa_supplicant HAL版本决定不同的逻辑:
* - v1.1会构造一个ISupplicant.IfaceInfo,并通过addInterface添加到
* wpa_supplicant interfaces,并从其返回结果中获取到对应的
* ISupplicantIface;
* - v1.0会通过listInterfaces获取所有的ISupplicant.IfaceInfo并
* 遍历,以找到匹配的结果,并再通过getInterface获取对应的
* ISupplicantIface;
* 然后,创建一个事件监听回调,并传递给wpa_supplicant,使其在STA模式
* 下状态发生改变时会触发回调,而该回调会进一步通知到WifiMonitor;
*
*/
if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
teardownInterface(iface.name);
return null;
}
iface.networkObserver = new NetworkObserverInternal(iface.id);
/*
* 调用INetworkManagementService的registerObserver注册连接状态事件回调
*/
if (!registerNetworkObserver(iface.networkObserver)) {
teardownInterface(iface.name);
return null;
}
//注册WifiMonitor回调
mWifiMonitor.startMonitoring(iface.name);
//立即上报一次iface的状态;
onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
//重置一些状态,包括IPv4地址、IPv6扩展支持等;
initializeNwParamsForClientInterface(iface.name);
return iface.name;
}
}
调用时序图参考如下:
可见,打开WIFI的调用过程中,有三个地方需要与HAL交互:
IWifiChip.createStaIface()
IWificond.createClientInterface()
ISupplicant
:- (V1.1)
ISupplicant.addInterface()
- (V1.0)
ISupplicant.listInterfaces() / ISupplicant.getInterfaces()
- (V1.1)
目前使用的机器走的是V1.1,因此后续以V1.1为例进行分析;
接下来逐一介绍:
IWifiChip
实现IWifiChip接口的代码路径为:hardware/interfaces/wifi/1.2/default/wifi_chip.cpp
Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::createStaIfaceInternal, hidl_status_cb);
}
validateAndCall()
是一个模板函数:
// Use for HIDL methods which return instance of WifiStatus and a single return
// value.
template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
Return<void> validateAndCall(
ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
Args&&... args) {
const auto lock = hidl_sync_util::acquireGlobalLock();
if (obj->isValid()) {
const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
const WifiStatus& status = std::get<0>(ret_pair);
const auto& ret_value = std::get<1>(ret_pair);
hidl_cb(status, ret_value);
} else {
hidl_cb(createWifiStatus(status_code_if_invalid),
typename std::remove_reference<ReturnT>::type());
}
return Void();
}
直接展开模板函数可得:
Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
const auto lock = hidl_sync_util::acquireGlobalLock();
if (isValid()) {
const auto& ret_pair = createStaIfaceInternal();
const WifiStatus& status = std::get<0>(ret_pair);
const auto& ret_value = std::get<1>(ret_pair);
hidl_status_cb(status, ret_value);
} else {
hidl_status_cb(createWifiStatus(WifiStatusCode::ERROR_WIFI_CHIP_INVALID),
typename std::remove_reference<ReturnT>::type());
}
return Void();
}
可见,返回结果是由createStaIfaceInternal()
函数提供;
std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
//如果当前工作模式不支持指定类型(此处为STA),则返回状态码ERROR_NOT_AVAILABLE,iface返回null
if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
bool iface_created = false;
/*
* 获取iface名称,默认返回wlan0(属性wifi.interface),如果wlan0已经被使用,返回
* wlan1(属性wifi.concurrent.interface)
* 若wlan1被使用,则返回wlan2(属性wifi.interface.2)
* 这里介绍下被使用的情况:
* wlan0被ap热点占用(部分设备支持ap与wifi同时打开,这种情况下就会出现一个wlan0,
* 一个wlan1)
* wlan0被2.4G热点占用,wlan1被5G热点占用,此时打开wifi就会走wlan2
*/
std::string ifname = allocateApOrStaIfaceName();
/*
* 检查这个iface名称是否有效,返回0表示:
* 1. socket通信建立失败 (低概率)
* 2. iface尚未创建
*/
if (!if_nametoindex(ifname.c_str())) {
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->QcAddInterface(getWlan0IfaceName(), ifname,
(uint32_t)IfaceType::STA);
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
iface_created = true;
}
//构造返回需要的IWifiIface(IWifiStaIface)
sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);
sta_ifaces_.push_back(iface);
//如果是新创建的iface,则添加到created_sta_ifaces_向量中
if (iface_created) created_sta_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
}
}
//返回SUCCESS状态码以及iface实例
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}
如上分析可知:
- 创建iface的核心方法在
QcAddInterface()
函数中 sta_ifaces_
向量中保存了所有创建的WifiStaIface
,created_sta_ifaces_
向量中仅保存随之创建了iface的WifiStaIface
继续查看QcAddInterface()
函数实现:
代码路径:hardware/interfaces/wifi/1.2/default/wifi_legacy_hal.cpp
wifi_error WifiLegacyHal::QcAddInterface(const std::string& iface_name,
const std::string& new_ifname,
uint32_t type) {
//global_func_table_.wifi_add_or_remove_virtual_intf即为wificonfig.cpp中
//wifi_add_or_remove_virtual_intf函数实现;
wifi_error status = global_func_table_.wifi_add_or_remove_virtual_intf(
getIfaceHandle(iface_name),
new_ifname.c_str(), type, true);
if (status == WIFI_SUCCESS) {
// refresh list of handlers now.
iface_name_to_handle_.clear();
status = retrieveIfaceHandles();
}
return status;
}
继续查看wificonfig.cpp
中wifi_add_or_remove_virtual_intf()
函数:
关于global_func_table_
中的函数指针怎么对应到wificonfig.cpp
中的wifi_add_or_remove_virtual_intf()
函数的,可以移步这里
代码路径:qcom/wlan/qcwcn/wifi_hal/wificonfig.cpp
#ifdef WCNSS_QTI_AOSP
wifi_error wifi_add_or_remove_virtual_intf(wifi_interface_handle iface,
const char* ifname, u32 iface_type,
bool create)
{
wifi_error ret;
WiFiConfigCommand *wifiConfigCommand;
//下方两个函数实现在hardware/qcom/wlan/qcwcn/wifi_hal/common.cpp
//强制类型转换
interface_info *ifaceInfo = getIfaceInfo(iface);
//强制类型转换为interface_info后取handle字段
wifi_handle wifiHandle = getWifiHandle(iface);
//构造一个WiFiConfigCommand,
wifiConfigCommand = new WiFiConfigCommand(wifiHandle, get_requestid(), 0, 0);
//QcAddInterface调用过来create恒为true
if (create) {
nl80211_iftype type;
//WifiChip::createStaIfaceInternal()调用过来恒为IfaceType::STA
switch(iface_type) {
case 0: /* IfaceType:STA */
type = NL80211_IFTYPE_STATION;
break;
case 1: /* IfaceType:AP */
type = NL80211_IFTYPE_AP;
break;
case 2: /* IfaceType:P2P */
type = NL80211_IFTYPE_P2P_DEVICE;
break;
default:
ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
ret = WIFI_ERROR_UNKNOWN;
goto done;
break;
}
//封装信息内容
wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE);
wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, ifaceInfo->id);
wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, ifname);
wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
} else {
wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
}
//通过Netlink发送消息到驱动侧
wifiConfigCommand->waitForRsp(false);
ret = wifiConfigCommand->requestEvent();
if (ret != WIFI_SUCCESS) {
ALOGE("wifi_add_or_remove_virtual_intf: requestEvent Error:%d", ret);
}
done:
delete wifiConfigCommand;
return ret;
}
后面就是驱动层的实现了,这里暂不讨论;
可见,IWifiChip.createStaIface
这一步主要是通知WIFI网卡驱动创建一个可用的(STA模式)Iface,如果已经创建,则直接使用即可;
这部分的流程比较简单,时序图参考如下:
IWifiCond
IWificond.createClientInterface()
的实现在wificond进程中:
代码路径:system/connectivity/wificond/server.cpp
Status Server::createClientInterface(const std::string& iface_name,
sp<IClientInterface>* created_interface) {
InterfaceInfo interface;
//如果setup失败,则直接返回,created_interface为空;
if (!SetupInterface(iface_name, &interface)) {
return Status::ok();
}
//构建一个ClientInterfaceImpl,并封装需要通过Netlink Socket发送的数据结构;
unique_ptr<ClientInterfaceImpl> client_interface(new ClientInterfaceImpl(
wiphy_index_,
interface.name,
interface.index,
interface.mac_address,
if_tool_.get(),
netlink_utils_,
scan_utils_));
*created_interface = client_interface->GetBinder();
BroadcastClientInterfaceReady(client_interface->GetBinder());
client_interfaces_[iface_name] = std::move(client_interface);
return Status::ok();
}
这里需要重点关注这个SetupInterface()
函数:
bool Server::SetupInterface(const std::string& iface_name,
InterfaceInfo* interface) {
//通过Netlink与内核通信,获取iface的信息,如果通信失败,直接返回false
if (!RefreshWiphyIndex()) {
return false;
}
//注册监听
netlink_utils_->SubscribeRegDomainChange(
wiphy_index_,
std::bind(&Server::OnRegDomainChanged,
this,
_1));
interfaces_.clear();
//通过Netlink获取对应的iface
if (!netlink_utils_->GetInterfaces(wiphy_index_, &interfaces_)) {
return false;
}
//如果名字匹配,则返回true
for (const auto& iface : interfaces_) {
if (iface.name == iface_name) {
*interface = iface;
return true;
}
}
return false;
}
重点在于RefreshWiphyIndex()
与NetlinkUtils::GetInterfaces()
两个函数:
RefreshWiphyIndex()
会调用NetlinkUtils::GetWiphyIndex()
,向内核发送NL80211_CMD_GET_WIPHY
请求,获取Wiphy的下标,如果获取成功则返回true
,反之返回false
;NetlinkUtils::GetInterfaces()
则是通过向内核发送NL80211_CMD_GET_INTERFACE
请求,附带wiphy_index
作为属性,尝试获取对应的InterfaceInfo
,获取成功返回true
,反之返回false
;
关于Wiphy
- 指的是Wireless Physical Layer,即linux内核net子系统中的无线网络(wireless)物理层;
HAL就到此为止,后面是内核部分的逻辑了,会单独写一篇介绍;
IWifiCond部分时序示意图如下:
ISupplicant
上面提到,ISupplicant在此题中讨论V1.1版本的逻辑,因此对应的HAL实现也应该看V1.1的wpa_supplicant:
代码路径:external/wpa_supplicant_8/wpa_supplicant/hidl/1.1/supplicant.cpp
:
Return<void> Supplicant::addInterface(
const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
{
return validateAndCall(
this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
&Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
}
validateAndCall()
同样是一个模板函数,照例展开:
Return<void> Supplicant::addInterface(
const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
{
if (this->isValid()) {
const auto& ret_pair =
addInterfaceInternal(iface_info);
const SupplicantStatus& status = std::get<0>(ret_pair);
const sp<ISupplicantIface> ret_value = std::get<1>(ret_pair);
hidl_cb(status, ret_value);
} else {
hidl_cb(
{SupplicantStatusCode::FAILURE_IFACE_INVALID, ""},
typename std::remove_reference<sp<ISupplicantIface>>::type());
}
return Void();
}
核心函数为addInterfaceInternal()
:
std::pair<SupplicantStatus, sp<ISupplicantIface>>
Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
{
android::sp<ISupplicantIface> iface;
...
//通过getInterfaceInternal尝试获取现有匹配的interface,如果已经存在,直接返回
SupplicantStatus status;
std::tie(status, iface) = getInterfaceInternal(iface_info);
if (status.code == SupplicantStatusCode::SUCCESS) {
return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
iface};
}
struct wpa_interface iface_params = {};
//驱动默认nl80211
iface_params.driver = kIfaceDriverName;
//由于传入的参数为IfaceType::STA,此处不讨论P2P的逻辑
if (iface_info.type == IfaceType::P2P) {
...
} else {
/*
* 确认配置文件是否存在,主要逻辑有如下几步:
* - 优先确认"/data/vendor/wifi/wpa/wpa_supplicant.conf"
* 是否存在且可写(RW),如果不可写,尝试chmod,如果失败,则返回-1,成功则返回0;
* - 如果前者不存在,则判断"/data/misc/wifi/wpa_supplicant.conf"是否存在,
* 如果存在则将其拷贝到"/data/vendor/wifi/wpa/wpa_supplicant.conf",
* 成功返回0,失败返回-1;如果文件不存在或不可读,返回1;
* - 如果前者返回1,则尝试拷贝"/vendor/etc/wifi/wpa_supplicant.conf"到
* "/data/vendor/wifi/wpa/wpa_supplicant.conf",同理成功返回0,
* 失败返回-1;如果文件不存在或不可读,返回1;
* - 如果前者返回1,则尝试拷贝"/system/etc/wifi/wpa_supplicant.conf"到
* "/data/vendor/wifi/wpa/wpa_supplicant.conf",同理成功返回0,
* 失败返回-1;如果文件不存在或不可读,返回1;
* - 如果前者依旧返回1,此时已经没有任何不就措施,函数返回-1
*/
if (ensureConfigFileExists(
kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
//表示配置文件未就绪,或为权限问题,或为文件不存在,HIDL状态码返回
//FAILURE_UNKNOWN,数据返回null;
return {{SupplicantStatusCode::FAILURE_UNKNOWN,
"Conf file does not exist"},
{}};
}
//读取配置文件,如果存在overlay,则使用confanother变量保存overlay文件路径:
//"/vendor/etc/wifi/wpa_supplicant_overlay.conf"
iface_params.confname = kStaIfaceConfPath;
int ret = access(kStaIfaceConfOverlayPath, R_OK);
if (ret == 0) {
iface_params.confanother = kStaIfaceConfOverlayPath;
}
}
iface_params.ifname = iface_info.name.c_str();
//核心调用,wpa_supplicant添加STA iface的关键函数;
struct wpa_supplicant* wpa_s =
wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
if (!wpa_s) {
return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
}
最后通过getInterfaceInternal获取对应的对象返回;
return getInterfaceInternal(iface_info);
}
可见,创建iface的工作在wpa_supplicant_add_iface()
中完成,这部分是wpa_supplicant
的逻辑了:
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
struct wpa_interface *iface,
struct wpa_supplicant *parent)
{
struct wpa_supplicant *wpa_s;
struct wpa_interface t_iface;
struct wpa_ssid *ssid;
...
//初始化一个wpa_s 对象,Android中会调用calloc进行内存分配;
wpa_s = wpa_supplicant_alloc(parent);
...
wpa_s->global = global;
t_iface = *iface;
//global->params中各个参数的值是main函数中解析cmdline中参数时确定的
//以具体的cmdline为准;
if (global->params.override_driver) {
...
t_iface.driver = global->params.override_driver;
}
if (global->params.override_ctrl_interface) {
...
t_iface.ctrl_interface =
global->params.override_ctrl_interface;
}
//初始化完成返回0,否则返回-1,这里是关键代码,且逻辑比较复杂
if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
...
//由于wpa_supplicant_init_iface流程很长,需要deinit来重置各种中间状态
wpa_supplicant_deinit_iface(wpa_s, 0, 0);
return NULL;
}
//顺利完成返回0,否则返回-1
if (wpas_notify_iface_added(wpa_s)) {
//由于无法通知状态,因此无效化该iface
wpa_supplicant_deinit_iface(wpa_s, 1, 0);
return NULL;
}
...
wpa_s->next = global->ifaces;
global->ifaces = wpa_s;
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
#ifdef CONFIG_P2P
...
#endif /* CONFIG_P2P */
return wpa_s;
}
有上面分析可知,wpa_supplicant
部分的处理关键在于wpa_supplicant_init_iface()
函数,后者展开就比较多了(350+行的函数)。
受限于篇幅,我这对函数实现进行了大量裁剪,以便于快速获取关键信息:
static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
const struct wpa_interface *iface)
{
struct wpa_driver_capa capa;
int capa_res;
u8 dfs_domain;
if (iface->confname) {
...
//读取配置文件与overlay文件,路径定义见上方ensureConfigFileExists()函数附近分析
wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
...
wpa_s->confanother = os_rel2abs_path(iface->confanother);
if (wpa_s->confanother &&
!wpa_config_read(wpa_s->confanother, wpa_s->conf)) {
...
return -1;
}
...
//如果ctrl_interface已经由cmdline指定,则此处不再取conf文件中的配置项
if (iface->ctrl_interface) {
os_free(wpa_s->conf->ctrl_interface);
wpa_s->conf->ctrl_interface =
os_strdup(iface->ctrl_interface);
}
...
}
//如果ifname过长,会导致拷贝失败,因此需要此处判断,如果字符串长度合理,则拷贝到wpa_s->ifname中;
if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
return -1;
}
os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
...
//初始化驱动并注册事件监听、处理的Handler,android采用linux内核,这里驱动就是nl80211;
//由于涉及到与内核交互,这里暂且不展开了,待驱动层分析时再继续
if (wpas_init_driver(wpa_s, iface) < 0)
return -1;
//初始化一些函数指针的映射;
if (wpa_supplicant_init_wpa(wpa_s) < 0)
return -1;
//将wpa_s中的部分信息通知到wpa_sm中,后者是一个cpp编写的状态机,实现的功能与JAVA层的StateMachine类似;
wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
NULL);
wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
//通过与驱动层(Android基于Linux内核,此处则为nl80211)通信,获取硬件的一些特性,包括支持的频段、通道、带宽、频率等信息;
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
&wpa_s->hw.num_modes,
&wpa_s->hw.flags,
&dfs_domain);
if (wpa_s->hw.modes) {
u16 i;
//遍历所有的支持模式,获取其最高的频率支持情况,并设置hw_capab(CAPAB_VHT > CAPAB_HT40 > CAPAB_HT)
for (i = 0; i < wpa_s->hw.num_modes; i++) {
if (wpa_s->hw.modes[i].vht_capab) {
wpa_s->hw_capab = CAPAB_VHT;
break;
}
if (wpa_s->hw.modes[i].ht_capab &
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)
wpa_s->hw_capab = CAPAB_HT40;
else if (wpa_s->hw.modes[i].ht_capab &&
wpa_s->hw_capab == CAPAB_NO_HT_VHT)
wpa_s->hw_capab = CAPAB_HT;
}
}
//通过与驱动交互,获取一些能力支持情况,主要包括加密、认证的算法支持情况;
capa_res = wpa_drv_get_capa(wpa_s, &capa);
//返回0表示获取成功,则将capa中获取的信息保存到wpa_s中;
if (capa_res == 0) {
wpa_s->drv_capa_known = 1;
wpa_s->drv_flags = capa.flags;
wpa_s->drv_enc = capa.enc;
wpa_s->drv_smps_modes = capa.smps_modes;
wpa_s->drv_rrm_flags = capa.rrm_flags;
wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
wpa_s->max_scan_ssids = capa.max_scan_ssids;
wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
wpa_s->max_sched_scan_plan_interval =
capa.max_sched_scan_plan_interval;
wpa_s->max_sched_scan_plan_iterations =
capa.max_sched_scan_plan_iterations;
wpa_s->sched_scan_supported = capa.sched_scan_supported;
wpa_s->max_match_sets = capa.max_match_sets;
wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
wpa_s->max_stations = capa.max_stations;
wpa_s->extended_capa = capa.extended_capa;
wpa_s->extended_capa_mask = capa.extended_capa_mask;
wpa_s->extended_capa_len = capa.extended_capa_len;
wpa_s->num_multichan_concurrent =
capa.num_multichan_concurrent;
wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
//mac地址随机化的支持情况,在驱动中是单独的变量记录,
//但是在wpa_s中是以标志位mac_addr_rand_supported 存放的,因此需要做转换
if (capa.mac_addr_rand_scan_supported)
wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
if (wpa_s->sched_scan_supported &&
capa.mac_addr_rand_sched_scan_supported)
wpa_s->mac_addr_rand_supported |=
(MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
}
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
wpa_s->p2p_mgmt = iface->p2p_mgmt;
...
//初始化wpa_supplicant层一些接口和参数
if (wpa_supplicant_driver_init(wpa_s) < 0)
return -1;
//初始化TDLS,该技术用于同一网络下设备间进行直连通信,需在驱动初始化后进行
if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa))
return -1;
//设置CountryCode
if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
return -1;
}
//初始化WPA(Wi-Fi Protected Access)
if (wpas_wps_init(wpa_s))
return -1;
//初始化GAS(Generic advertisement service) server - struct gas_server
wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx);
...
//初始化DPP(Device Provision Protocol)
if (wpas_dpp_init(wpa_s) < 0)
return -1;
//初始化eapol,其会作为后续连接时四次握手的传输协议使用
if (wpa_supplicant_init_eapol(wpa_s) < 0)
return -1;
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
if (wpa_s->ctrl_iface == NULL) {
return -1;
}
wpa_s->gas = gas_query_init(wpa_s);
if (wpa_s->gas == NULL) {
return -1;
}
if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) ||
wpa_s->p2p_mgmt) &&
wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
return -1;
}
if (wpa_bss_init(wpa_s) < 0)
return -1;
if (capa_res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0)
return -1;
if (pcsc_reader_init(wpa_s) < 0)
return -1;
if (wpas_init_ext_pw(wpa_s) < 0)
return -1;
wpas_rrm_reset(wpa_s);
wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
hs20_init(wpa_s);
wpa_supplicant_set_default_scan_ies(wpa_s);
return 0;
}
wpa_supplicant_init_iface()
这个函数调用的东西非常多。篇幅有限,这里无法一一展开分析,先上一个大致的时序图,后续分析wpa_supplicant的时候再着重介绍;
最后,再附上一个合体的时序图: