[Android]Android P(9) WIFI学习笔记 - HAL (1)

前文回顾

前言

  1. 基于Android P源码学习;
  2. 代码片为了方便阅读段经过删、裁减,请以实际源码为准;

入口

根据前两篇的分析结果,调用栈都汇聚到了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
  • WifiMonitor mWifiMonitor

    • 一个负责收集、分发wpa_supplicant状态的工具类;
  • INetworkManagementService:mNwManagementService

    • INetworkManagementService实现类的的客户端实例
  • PropertyService:mPropertyService

    • 类型为PropertyService的接口,实现类型为SystemPropertyService,本质是对android.os.SystemPropertiesget/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为例进行分析;

接下来逐一介绍:

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_向量中保存了所有创建的WifiStaIfacecreated_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.cppwifi_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的时候再着重介绍;

在这里插入图片描述
最后,再附上一个合体的时序图:

在这里插入图片描述

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
7 Android的Audio系统 7.1 Audio系统的综述 Audio系统架构和代码路径 7.2 meida库中Audio相关接口 Audio系统的本地核心接口,类的层次结构 7.3 Audio系统和上层接口 Audio系统的JAVA层次的接口 7.4 Audio硬件抽象层 Audio系统的移植,Audio硬件抽象层的实现方法 ALSA Audio HAL实现 8 Android的Video 输入输出系统 8.1 Video输入输出系统的综述 视频输入输出系统架构和代码路径 8.2 Overlay系统 视频输出系统的结构 8.3 Overlay的硬件抽象层 视频输出系统的移植,抽象层实现 8.4 Camera系统与上层接口 Camera系统的层次结构 8.5 Camera的硬件抽象层 Camera系统的移植 Camera和Overlay的结合与数据传送 9 Android的多媒体系统 9.1 多媒体系统的结构 应用到底层的层次结构 9.2 media核心库的结构 多媒体本地代码的结构 9.3 多媒体部分的上层代码 照相机,媒体播放,媒体录制的框架结构 9.4 PackageVideo的架构 OpenMAX编译码插件的集成 9.5 stagefright的架构与实现(Éclair新增) 10 Android的电话系统 10.1 电话系统结构 Android电话系统的层次结构 10.2 电话系统组成部分 Android电话系统的本地和JAVA程序运行流程 10.3 电话系统移植层 为特定Modem移植的方法 11 Android的连接部分 11.1 WIFI无线局域网的部分 11.2 蓝牙部分 11.3 GPS部分 12 Android的传感器系统 12.1 Android传感器系统概述 12.2 Android传感器系统的层次结构 12.3 Android传感器系统的硬件抽象层和移植 重力加速度等传感器的移植 12.4 Android传感器系统的使用 1.HAL 技术详解 1.1 HAL 架構解析 1.2 Service与Manager的意义与用途 1.3 libhardware 与 HAL API 1.4 Stub & Module 的观念 1.5 专题讨论:定义并撰写第一个HAL Stub 2.HAL Development 2.1 HAL Stub Analysis and Design (OOAD) 2.2 HAL Stub Class 2.3 HAL Stub Interface 2.4 专题讨论:开发 LED 的 HAL 模组 3.Android API Design 3.1 Abstract Class and Interface in Android 3.2 The Reuse of Framework Design 3.3 OOAD of new APIs 3.4 Implementaion of new APIs 3.5 Singleton Pattern to Android APIs 3.6 Factory Method Pattern to Android APIs 4.Extend Android API 4.1 如何加入 API 至 Android Framework 4.2 如何编译并制作独立 JAR 档 4.3 上机实验:开发LedService API 与制作mokoid.jar 程式库 5.JNI & Runtime Library 5.1 什么是 JNI 5.2 如何撰写 JNI & Native Method 5.3 如何制作 Android Runtime Library 5.4 专题讨论:如何开发与制作Runtime Library 6.5 专题讨论:SensorManager与SensorService实例 7.SystemService 与 HAL 整合7.1 IPC、 Remote method call与Binder观念说明 7.2 AIDL 介绍与IInterface设计观念解析 7.3 Activity & ApplicationContext 7.4 ServiceManager 7.5 专题讨论:LedService设计与ILedService探讨 8.Manager API (Refinement-架构优化) 8.1 SensorManager与 SensorService实例探讨 8.2 Remote Object观念与IBinder介绍 8.3 如何以Proxy Object整合Android Service 8.4 Long operations 的解析与实作细节 8.5 RemoteException 的解析与实作细节 8.6 Handler 与 Message 的解析与实作细节 8.7 Error Handling 9.专题探讨 9.1 整合驱动程式至Android 框架 9.2 撰写Anroid应用程式以控制LED 9.3 标准的Android HAL 架构 9.4 HAL Stub OOAD & Implementation
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值