上一篇讲到SoftApManager.IdleState状态中处理CMD_START消息,这个消息用来打开热点功能。我们从这里继续看热点功能基本流程。

public boolean processMessage(Message message) {switch (message.what) {case CMD_START:WifiConfiguration config = (WifiConfiguration) message.obj;mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(mWifiNativeInterfaceCallback);int result = startSoftAp((WifiConfiguration) message.obj);transitionTo(mStartedState);}
}

这里有两个重要的方法,一个是WifiNative.setupInterfaceForSoftApMode和startSoftAp,现在先看setupInterfaceForSoftApMode的实现。

@WifiNative.java
public String setupInterfaceForSoftApMode(@NonNull InterfaceCallback interfaceCallback) {startHal();startHostapd()
}

startHal用来启动WIFI hal层代码,对hal进行初始化。将通过HIDL和hal进行通信。

startHal()  -> WifiNative.javastartVendorHal() -> WifiVendorHal.javastart() -> HalDeviceManager.javamWifi = IWifi.getService(true /* retry */);mWifi.start();

mWifi是hal层中实现的一个服务,现在需要进入到hardware/interfaces/wifi/1.3/default/wifi.h 目录下去查看start()的实现。

@hardware/interfaces/wifi/1.3/default/wifi.cpp
Return<void> Wifi::start(start_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,&Wifi::startInternal, hidl_status_cb);
}WifiStatus Wifi::startInternal() {WifiStatus wifi_status = initializeModeControllerAndLegacyHal();chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,iface_util_, feature_flags_);return wifi_status;
}

initializeModeControllerAndLegacyHal()函数中将原始hal层的init函数。legacy_hal_为WifiLegacyHal类的实例。WifiLegacyHal::initialize()方法为:

@hardware/interfaces/wifi/1.3/default/wifi_legacy_hal.cpp
wifi_error WifiLegacyHal::initialize() {initHalFuncTableWithStubs(&global_func_table_)) ;wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
}

这里的func_tab在hardware/qcom/wlan/qcwcn/wifi_hal/wifi_hal.cpp中实现,里面有wifi操作的各种方法,通过这个table完成对WIFI的操作。init方法中主要做的事情是操作和驱动程序的nl socket连接,完成通信基础。能和驱动建立连接,hal层就算初始化完成了。

在初始化hal完成后, 实例化了一个WifiChip元素,WifiChip构造方法参数中是一些使用的参数,比如legacy_hal_,可以用来操作WIFI芯片。

到这里,在HalDeviceManager中的mWifi.start()就基本完成。

在WifiNative中,除了有startHal()外,还有startHostapd(),我们看startHostapd实现。

    private boolean startAndWaitForHostapdConnection() {// Start initialization if not already started.if (!mHostapdHal.isInitializationStarted()&& !mHostapdHal.initialize()) {return false;}if (!mHostapdHal.startDaemon()) {Log.e(TAG, "Failed to startup hostapd");return false;}boolean connected = false;int connectTries = 0;while (!connected && connectTries++ < CONNECT_TO_HOSTAPD_RETRY_TIMES) {// Check if the initialization is complete.connected = mHostapdHal.isInitializationComplete();if (connected) {break;}try {Thread.sleep(CONNECT_TO_HOSTAPD_RETRY_INTERVAL_MS);} catch (InterruptedException ignore) {}}return connected;

这里调用mHostapdHal.startDaemon()来启动hostapd进程。startDaemon()方法,猜测是通过过去一个没有打开的服务,来记过服务。hostapd的服务定义在external/wpa_supplicant_8/hostapd/hostapd.android.rc.

14 service hostapd /vendor/bin/hw/hostapd -dd -g /data/vendor/wifi/hostapd/global
15     interface android.hardware.wifi.hostapd@1.0::IHostapd default
16     interface android.hardware.wifi.hostapd@1.1::IHostapd default
17     class main
18     capabilities NET_ADMIN NET_RAW
19     user wifi
20     group wifi net_raw net_admin
21     disabled
22     oneshot

这样hostapd进程就运行起来。

退回到SoftApManager类的Idle状态,setupInterfaceForSoftApMode()启动wifi hal层和hostapd后,执行startSoftAp()方法。

@SoftApManager.java
private int startSoftAp(WifiConfiguration config) {WifiConfiguration localConfig = new WifiConfiguration(config);int result = ApConfigUtil.updateApChannelConfig(mWifiNative, mCountryCode,mWifiApConfigStore.getAllowed2GChannel(), localConfig);mWifiNative.startSoftAp(mApInterfaceName, localConfig, mSoftApListener);
}@WifiNative.java
public boolean startSoftAp(@NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) {// 注册回调处理方法mWificondControl.registerApListener(ifaceName, listener);// 启动热点mHostapdHal.addVendorAccessPoint(ifaceName, config, listener);// 设置WIFI版本WifiInjector.getInstance().getWifiApConfigStore().setWifiGeneration(wifiGeneration);
}

我们看addVendorAccessPoint的实现方法:

@HostapdHal.java
public boolean addVendorAccessPoint(@NonNull String ifaceName, @NonNull WifiConfiguration config, SoftApListener listener) {// ap配置信息,包括信道信息,ssid,加密方式信息,密码,是否隐藏// vendorIfaceParams1_1Z在hidl定义,将java中的配置信息设置到hidl结构中vendorIfaceParams1_1.VendorV1_0 = vendorIfaceParams;vendorIfaceParams1_1.vendorChannelParams.channelParams = ifaceParams.channelParams;vendorIfaceParams1_1.vendorEncryptionType = getVendorEncryptionType(config);vendorIfaceParams1_1.oweTransIfaceName = (config.oweTransIfaceName != null) ? config.oweTransIfaceName : "";// 根据是否打开acs选择信道if (mEnableAcs) {vendorIfaceParams1_1.vendorChannelParams.acsChannelRanges.addAll(mVendorAcsChannelRanges);}// 进入到hal中,在hal中将通过打开hostap打开热点,同事将配置信息通过高通sdk设置到驱动HostapdStatus status =iHostapdVendorV1_1.addVendorAccessPoint_1_1(vendorIfaceParams1_1, nwParams);
}

addVendorAccessPoint_1_1()函数在hidl中实现,进入到external/wpa_supplicant_8/hostapd/hidl/vendor/1.1/hostapd_vendor.cpp查看其实现。

@hostapd_vendor.cpp
HostapdStatus HostapdVendor::__addVendorAccessPointInternal_1_1(const VendorIfaceParams& v_iface_params, const NetworkParams& nw_params)
{// 通过qsap,也就是高通sdk设置参数const auto conf_file_path =AddOrUpdateHostapdConfig(v_iface_params, nw_params);// 通过hostapd来打开热点hostapd_add_iface(interfaces_, add_iface_param_vec.data());hostapd_enable_iface(iface_hapd->iface);
}

AddOrUpdateHostapdConfig()通过qsap这个高通sdk进行操作,其主要工作有两个:

  • 把配置信息比如ssid,信道,加密方式等写入到/data/vendor/wifi/hostapd/hostapd.conf这个配置文件中。在hostapd中,打开热点时,将通过external/wpa_supplicant_8/hostapd/config_file.c 读取文件信息作为热点设置信息。
  • 一些操作指令,将通过io指令下发到驱动,直接指导驱动执行,比如断开sta操作代码:
void qsap_disassociate_sta(s8 *pVal, s8 *presp, u32 *plen)
{sock = socket(AF_INET, SOCK_DGRAM, 0);strlcpy(wrq.ifr_name, pif, sizeof(wrq.ifr_name));ret = ioctl(sock, QCSAP_IOCTL_DISASSOC_STA, &wrq);close(sock);
}

我们回到AddOrUpdateHostapdConfig()方法实现如下:

@hostapd_vendor.cpp
constexpr char kQsapSetFmt[] = "softap qccmd set%s %s=%s";
std::string AddOrUpdateHostapdConfig(const IHostapdVendor::VendorIfaceParams& v_iface_params,const IHostapd::NetworkParams& nw_params)
{const std::string ssid_as_string = ss.str();qsap_cmd(StringPrintf(kQsapSetFmt, dual_mode_str, "ssid2", ssid_as_string.c_str()));qsap_cmd(StringPrintf(kQsapSetFmt, dual_mode_str, "channel", std::to_string(channelParams.channel).c_str()));}...
}

qsap_cmd()在qsap中实现,用来设置指令。

// 将字符串指令拆分
int qsap_cmd(std::string cmd)
{for(auto& s: tokens) {if (argc >= max_arg_size) {wpa_printf(MSG_ERROR, "Command too long");return -1;}data[argc] = strdup(s.c_str());argc++;}run_qsap_cmd(argc, argv);
}int run_qsap_cmd(int argc, char** argv) {int ret = 0;if (argc < 3)return -1;if (!strcmp(argv[1], "qccmd")) {ret = qsap_hostd_exec(argc, argv);} else if (!strcmp(argv[1], "create") &&qsap_add_or_remove_interface(argv[2], 1)) {} else if (!strcmp(argv[1], "remove") &&qsap_add_or_remove_interface(argv[2], 0)) {} else if (!strcmp(argv[1], "bridge")) {ret = qsap_control_bridge(argc, argv);} else if (!strcmp(argv[1], "setsoftap")) {ret = qsapsetSoftap(argc, argv);} else {ret = -1;}return ret;
}

Android10 高通平台 softap热点基本流程2相关推荐

  1. Android10 高通平台 softap热点基本流程1

    softap的入口在ConnectivityManager.java中,作为连接的一部分.老版本Android的入口在WifiManager.java中.应用启动softap时,调用Connectiv ...

  2. 高通平台RF配置流程

    高通平台RF配置流程 **注:**本文参考项目路径和代码为SIM7600 LE20分支 1 准备工作 需要的资料: 各个器件的datasheet 原理图 逻辑表(内容包含支持哪些制式.band,各个b ...

  3. 高通平台Bootloader启动流程【转】

    本文转载自:http://blog.csdn.net/fang_first/article/details/49615631 ====================基本知识============= ...

  4. 高通平台msm8917蓝牙mac地址流程

    高通平台msm8917蓝牙mac地址流程 Where is the BD address? BD address can be saved in following places: modem NV ...

  5. 高通android开源代码下载,高通平台Android源码bootloader分析之sbl1(三)

    前两篇博文分析了启动流程.代码流程.cdt,接下来就分析另外几个需要格外关注的部分. ##log系统 sbl1中的log系统也是sbl1部分调试会经常接触得部分高通平台在sbl中做的log系统并不是很 ...

  6. android加载efi分区,高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

  7. 高通平台sensor学习

    刚入行驱动时最先接触调试的外设模块便是sensor,一直都是零零散散的记录,这次终于下定决心对自己所学做一个系统的总结. sensor作为一款常用的外设,虽不起眼但是很多功能确实离不开它.比如我们手机 ...

  8. 高通平台android开发总结 MSM平台上的AMSS

    http://blog.csdn.net/mirkerson/article/details/7691029 MSM平台上的AMSS REX启动分析--基于Qualcomm平台 1.高通平台andro ...

  9. 高通平台 lcd driver 调试小结

    一.概述 1.1 简介 本文档主要包括LCD模块的驱动流程分析.Framebuffer相关知识.Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解. 1.2  开发环境 And ...

最新文章

  1. 【智力问题】25匹马赛跑,每次只能跑5匹马,最快能赛几次找出跑得最快的3匹马?赛跑不能计时,并假设每匹马的速度是恒定不变的。...
  2. Scala _11SparkWordCountscala语言java语言
  3. linux mysql odbc驱动安装_MySQL ODBC 驱动安装
  4. 在哪里搜python题_robots文件生成
  5. 银行卡号与开户行对照文档
  6. 那些漂亮的sci论文图一般用什么软件制作的?
  7. 使用java解压GZip文件
  8. 赛思互动:管理学最重要的八大定理
  9. TCP接收到重叠数据(overlap)后的行为解析-附带一个有关Delay ACK和超时重传的优化
  10. python tk/ttk制作 安卓群控助手,多台设备多任务多线程执行
  11. 动手智能小车记(5)-坦克底盘硬件模块大杂烩
  12. 【备忘】总结一些Java学习者经常去的网站及论坛
  13. uniapp H5嵌套通讯方案-webviewiframe
  14. 人工智能定义的 IT 基础设施浅析
  15. 程序员只能在一线城市么?
  16. 解决XAMPP中无法勾选/无服务/modules无反应/Service灰框/无✓X/提供虚拟服务器
  17. EP4CE10系列芯片引脚图
  18. centos8以后版本突然不能上网解决
  19. 正则表达式新手入门笔记(一)
  20. 关于CAD2022重装显示已安装,需要删除注册表中的CAD文件(需仔细)

热门文章

  1. eclipse导入项目出现很多小红叉以及a jni error has occurred please check your installation and try again问题的解决
  2. R语言可视化【ggplot2】
  3. 项目经理必知的项目成本控制方法
  4. 为什么Scala这么受欢迎
  5. C语言求职笔试题,c语言面试最必考的十道试题,求职必看!!!
  6. HTML5系列代码:仅设置列的数目
  7. optimizer.load_state_dict()
  8. 国外AI工程师讲述:深度学习与目标检测,理论和实践果然两码事
  9. Ajax图书管理系统-完整代码与细节部分详细讲解
  10. 《linux系统运维》学习笔记