一 前言

在上一篇分析了wifi启动的流程,从Android应用层一直分析到了Java框架层,这次我们接着往下走流程。如果没有看上一篇的建议先回头看看   Wifi模块—源码分析Wifi启动1(Android P)这样能更好地认知和把握wifi的启动过程。

二 图示调用流程

这个调用流程图也是基于上一篇的流程图进一步完善的得到的。

三 代码具体流程

1 应用层

2 java 框架层

前面部分直接看 Wifi模块—源码分析Wifi启动1(Android P),这一层也不标注明确的节点数值,因为这一层的前面调用流程部分并未全部加到这里。所以直接去看前面一篇会更清晰。

我们直接从WifiNative.java这个类开始看。

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

/**

* Setup an interface for Client mode operations.

*

* * This method configures an interface in STA mode in all the native daemons

* (wificond, wpa_supplicant & vendor HAL).

*

* @param lowPrioritySta The requested STA has a low request priority (lower probability of

* getting created, higher probability of getting destroyed).

* @param interfaceCallback Associated callback for notifying status changes for the iface.

* @return Returns the name of the allocated interface, will be null on failure.

*/

public String setupInterfaceForClientMode(boolean lowPrioritySta,

@NonNull InterfaceCallback interfaceCallback) {

synchronized (mLock) {

if (!startHal()) {

Log.e(TAG, "Failed to start Hal");

mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();

return null;

}

if (!startSupplicant()) {

Log.e(TAG, "Failed to start supplicant");

mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();

return null;

}

Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);

if (iface == null) {

Log.e(TAG, "Failed to allocate new STA iface");

return null;

}

iface.externalListener = interfaceCallback;

iface.name = createStaIface(iface, lowPrioritySta);

if (TextUtils.isEmpty(iface.name)) {

Log.e(TAG, "Failed to create STA iface in vendor HAL");

mIfaceMgr.removeIface(iface.id);

mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();

return null;

}

if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {

Log.e(TAG, "Failed to setup iface in wificond on " + iface);

teardownInterface(iface.name);

mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();

return null;

}

if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {

Log.e(TAG, "Failed to setup iface in supplicant on " + iface);

teardownInterface(iface.name);

mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();

return null;

}

iface.networkObserver = new NetworkObserverInternal(iface.id);

if (!registerNetworkObserver(iface.networkObserver)) {

Log.e(TAG, "Failed to register network observer on " + iface);

teardownInterface(iface.name);

return null;

}

mWifiMonitor.startMonitoring(iface.name);

// Just to avoid any race conditions with interface state change callbacks,

// update the interface state before we exit.

onInterfaceStateChanged(iface, isInterfaceUp(iface.name));

initializeNwParamsForClientInterface(iface.name);

Log.i(TAG, "Successfully setup " + iface);

return iface.name;

}

}

看一些关键性的操作:

启动Hal:startHal()

启动supplicant:startSupplicant()

加载驱动(loadDriver):setupInterfaceForClientMode()

启动WifiMonitor:WifiMonitor.startMonitoring()

这里我们就选择  启动Hal:startHal() 这条线走下去。

/** Helper method invoked to start supplicant if there were no ifaces */

private boolean startHal() {

synchronized (mLock) {

if (!mIfaceMgr.hasAnyIface()) {

if (mWifiVendorHal.isVendorHalSupported()) {

if (!mWifiVendorHal.startVendorHal()) {

Log.e(TAG, "Failed to start vendor HAL");

return false;

}

} else {

Log.i(TAG, "Vendor Hal not supported, ignoring start.");

}

}

return true;

}

}

看mWifiVendorHal.startVendorHal()。

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java

/**

* Bring up the HIDL Vendor HAL.

* @return true on success, false otherwise.

*/

public boolean startVendorHal() {

synchronized (sLock) {

if (!mHalDeviceManager.start()) {

mLog.err("Failed to start vendor HAL").flush();

return false;

}

mLog.info("Vendor Hal started successfully").flush();

return true;

}

}

看mHalDeviceaManager.start()。

frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java

/**

* Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or

* the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on

* success.

*

* Note: direct call to HIDL.

*/

public boolean start() {

return startWifi();

}

继续看startWifi()。

private boolean startWifi() {

if (VDBG) Log.d(TAG, "startWifi");

synchronized (mLock) {

try {

if (mWifi == null) {

Log.w(TAG, "startWifi called but mWifi is null!?");

return false;

} else {

int triedCount = 0;

while (triedCount <= START_HAL_RETRY_TIMES) {

WifiStatus status = mWifi.start();

if (status.code == WifiStatusCode.SUCCESS) {

initIWifiChipDebugListeners();

managerStatusListenerDispatch();

if (triedCount != 0) {

Log.d(TAG, "start IWifi succeeded after trying "

+ triedCount + " times");

}

return true;

} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {

// Should retry. Hal might still be stopping.

Log.e(TAG, "Cannot start IWifi: " + statusString(status)

+ ", Retrying...");

try {

Thread.sleep(START_HAL_RETRY_INTERVAL_MS);

} catch (InterruptedException ignore) {

// no-op

}

triedCount++;

} else {

// Should not retry on other failures.

Log.e(TAG, "Cannot start IWifi: " + statusString(status));

return false;

}

}

Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");

return false;

}

} catch (RemoteException e) {

Log.e(TAG, "startWifi exception: " + e);

return false;

}

}

}

主要看WifiStatus status = mWifi.start(),先看下mWifi是什么。

/**

* Wrapper function to access the HIDL services. Created to be mockable in unit-tests.

*/

protected IWifi getWifiServiceMockable() {

try {

return IWifi.getService();

} catch (RemoteException e) {

Log.e(TAG, "Exception getting IWifi service: " + e);

return null;

}

}

这里返回的是IWifi的服务端。至此我们开始进入HIDL。

3 HIDL

HIDL 读作 hide-l,Wifi到Andoid O之后所以Android P也一样不再使用jni,而是使用HIDL,Hardware Interface Define Language。

3.1 hardware/interfaces/wifi/1.0/IWifi.hal

/**

* Perform any setup that is required to make use of the module. If the module

* is already started then this must be a noop.

* Must trigger |IWifiEventCallback.onStart| on success.

*

* @return status WifiStatus of the operation.

* Possible status codes:

* |WifiStatusCode.SUCCESS|,

* |WifiStatusCode.NOT_AVAILABLE|,

* |WifiStatusCode.UNKNOWN|

*/

@entry

@callflow(next={"registerEventCallback", "start", "stop", "getChip"})

start() generates (WifiStatus status);

系统编译的时候会自动产生IWifi.java文件。

out/soong/.intermediates/hardware/interfaces/wifi/1.0/android.hardware.wifi_V1.0-java_gen_java/gen/android/hardware/wifi/V1_0/IWifi.java

IWifi.java的getService方法

public static IWifi getService(String serviceName) throws android.os.RemoteException {

return IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));

}

再看一下 IWifi.java的asInterface方法。

IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));

从而我们就可以知道IWifi对应的服务端了。

3.2 hardware/interfaces/wifi/1.2/default/wifi.cpp

按照IWifi.java的代码接下来的调用路径应该在hardware/interfaces/wifi/1.0/default/,但没有发现这个路径下有wifi.cpp这个文件,hardware/interfaces/wifi/1.2/default/倒是有wifi.cpp,这个我也不清楚为什么。那就先按这个调用流程走下去吧。

Return Wifi::start(start_cb hidl_status_cb) {

return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,

&Wifi::startInternal, hidl_status_cb);

}

看startInternal()。

WifiStatus Wifi::startInternal() {

if (run_state_ == RunState::STARTED) {

return createWifiStatus(WifiStatusCode::SUCCESS);

} else if (run_state_ == RunState::STOPPING) {

return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,

"HAL is stopping");

}

WifiStatus wifi_status = initializeModeControllerAndLegacyHal();

if (wifi_status.code == WifiStatusCode::SUCCESS) {

// Create the chip instance once the HAL is started.

chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,

feature_flags_);

run_state_ = RunState::STARTED;

for (const auto& callback : event_cb_handler_.getCallbacks()) {

if (!callback->onStart().isOk()) {

LOG(ERROR) << "Failed to invoke onStart callback";

};

}

LOG(INFO) << "Wifi HAL started";

} else {

for (const auto& callback : event_cb_handler_.getCallbacks()) {

if (!callback->onFailure(wifi_status).isOk()) {

LOG(ERROR) << "Failed to invoke onFailure callback";

}

}

LOG(ERROR) << "Wifi HAL start failed";

}

return wifi_status;

}

WifiStatus Wifi::initializeModeControllerAndLegacyHal() {

if (!mode_controller_->initialize()) {

LOG(ERROR) << "Failed to initialize firmware mode controller";

return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);

}

legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();

if (legacy_status != legacy_hal::WIFI_SUCCESS) {

LOG(ERROR) << "Failed to initialize legacy HAL: "

<< legacyErrorToString(legacy_status);

return createWifiStatusFromLegacyError(legacy_status);

}

return createWifiStatus(WifiStatusCode::SUCCESS);

}

接着看wifi_mode_controller.cpp得initialize()方法。

3.3 hardware/interfaces/wifi/1.2/default/wifi_mode_controller.cpp

bool WifiModeController::initialize() {

if (!driver_tool_->LoadDriver()) {

LOG(ERROR) << "Failed to load WiFi driver";

return false;

}

return true;

}

再继续看driver_tool.cpp这里开始走到WPA适配层了。

4 WPA适配层(硬件抽象层 HAL)

HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。

wpa_supplicant适配层是通用的wpa_supplicant的封装,在Android中作为WiFi部分的硬件抽象层来使用。wpa_supplicant适配层主要用于与wpa_supplicant守护进程的通信,以提供给Android框架使用,它实现了加载、控制和消息监控等功能。

4.1frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp

bool DriverTool::LoadDriver() {

return ::wifi_load_driver() == 0;

}

4.2 frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp

int wifi_load_driver() {

#ifdef WIFI_DRIVER_MODULE_PATH

if (is_wifi_driver_loaded()) {

return 0;

}

if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;

#endif

#ifdef WIFI_DRIVER_STATE_CTRL_PARAM

if (is_wifi_driver_loaded()) {

return 0;

}

if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1;

#endif

property_set(DRIVER_PROP_NAME, "ok");

return 0;

}

看is_wifi_driver_loaded()。

int is_wifi_driver_loaded() {

char driver_status[PROPERTY_VALUE_MAX];

#ifdef WIFI_DRIVER_MODULE_PATH

FILE *proc;

char line[sizeof(DRIVER_MODULE_TAG) + 10];

#endif

if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) ||

strcmp(driver_status, "ok") != 0) {

return 0; /* driver not loaded */

}

#ifdef WIFI_DRIVER_MODULE_PATH

/*

* If the property says the driver is loaded, check to

* make sure that the property setting isn't just left

* over from a previous manual shutdown or a runtime

* crash.

*/

if ((proc = fopen(MODULE_FILE, "r")) == NULL) {

PLOG(WARNING) << "Could not open " << MODULE_FILE;

property_set(DRIVER_PROP_NAME, "unloaded");

return 0;

}

while ((fgets(line, sizeof(line), proc)) != NULL) {

if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {

fclose(proc);

return 1;

}

}

fclose(proc);

property_set(DRIVER_PROP_NAME, "unloaded");

return 0;

#else

return 1;

#endif

}

5 wpa_supplicant

wpa_supplicant是一个开源项目,已经被移植到Linux,Windows以及很多嵌入式系统上。它是WPA的应用层认证客户端,负责完成认证相关的登录、加密等工作。wpa_supplicant的源代码目录为:

/external/wpa_supplicant_8/

wpa_supplicant是一个独立运行的守护进程,其核心是一个消息循环,在消息循环中处理WPA状态机、控制命令、驱动事件、配置信息等。wpa_supplicant有很多控制接口,也提供命令行和通行界面的控制模式:而Android与wpa_supplicant的通信通过Socket完成

6 Linux Kernel

Wifi的内核驱动程序

kernel/driver/net/wireless/

vendor/gcom/opensource/wlan/

java wifi模块源码_Wifi模块相关推荐

  1. Wifi模块—源码分析Wifi热点扫描2(Android P)

    一 前言 这次接着讲Wifi工程流程中的Wifi热点扫描过程部分的获取扫描结果的过程,也是Wifi扫描过程的延续,可以先看前面Wifi扫描的分析过程. Wifi模块-源码分析Wifi热点扫描(Andr ...

  2. Wifi模块—源码分析Wifi热点扫描(Android P)

    一 前言 这次接着讲Wifi工程流程中的Wifi热点查找过程,也是Wifi启动的过程延续,Wifi启动过程中会更新Wifi的状态,框架层也有相应广播发出,应用层接收到广播后开始进行热点的扫描.可以先看 ...

  3. Wifi模块—源码分析Wifi启动(Android P)

    一.前言 Android P在wifi这块改动挺大的,Wifi到AndoidO之后不再使用jni,所以AndroidP也一样不再使用jni来实现Java代码与本地的C/C++代码交互,而是使用HIDL ...

  4. Wifi模块—源码分析Wifi启动2(Android P)

    一 前言 在上一篇分析了wifi启动的流程,从Android应用层一直分析到了Java框架层,这次我们接着往下走流程.如果没有看上一篇的建议先回头看看   Wifi模块-源码分析Wifi启动1(And ...

  5. Java进销存系统源码 采购模块 收货/质检/入库 动态实时库存

    Java进销存系统源码 采购模块 收货/质检/入库 动态实时库存 零星采购.一揽子采购.采购计划.合同采购 采购入库.采购退货.杂项入库.生产入库 多库存组织.库存盘点.库存调拨 销售模块 出库 主数 ...

  6. Dubbo协议模块源码剖析

    Dubbo协议模块源码剖析 目录 概 述 RPC协议报文编码与实现详解 RPC 传输实现: 拆包与粘包解决办法: Dubbo 报文格式 分析: 小结: 参考资料和推荐阅读 LD is tigger f ...

  7. ensp大型网络环境设计与实现_mongodb内核源码设计实现、性能优化、最佳运维系列-网络传输层模块源码实现三...

    1. 说明 在之前的<<Mongodb网络传输处理源码实现及性能调优-体验内核性能极致设计>>和<<mongodb内核源码设计实现.性能优化.最佳运维系列-tran ...

  8. 分布式事务中间件 Fescar—RM 模块源码解读

    2019独角兽企业重金招聘Python工程师标准>>> 前言 在SOA.微服务架构流行的年代,许多复杂业务上需要支持多资源占用场景,而在分布式系统中因为某个资源不足而导致其它资源占用 ...

  9. mysql 线程池源码模块_易语言Mysql线程池2.0模块源码

    易语言Mysql线程池2.0模块源码 易语言Mysql线程池2.0模块源码 系统结构:GetThis,初始化,关闭类线程,线程_测试,其他_附加文本,连接池初始化,取mysql句柄,释放mysql句柄 ...

最新文章

  1. PAT_B_1027 打印沙漏
  2. Aspectj 实现Method条件运行
  3. 自学python-python自学起来难不难?python学习路线分享
  4. Java集合sort()
  5. 深度学习网络训练中出现nan的原因分析
  6. Summernote个性化定制使用帮助(三)
  7. 通过UDP广播实现Android局域网Peer Discovering
  8. 返利网拼团小程序,10人拼团7人返利
  9. LAIC2022司法人工智能挑战赛 - 司法文本小样本多任务Baseline
  10. 按键精灵定义全局变量_按键精灵全局环境变量
  11. MYSQL 名人博客
  12. 暗态图像处理论文:A Bio-Inspired Multi-Exposure Fusion Framework for Low-light Image Enhancement
  13. 团队里不能留的三种人
  14. 扇贝python编程课_扇贝编程app下载-扇贝编程手机版python「附如何设置自由职业」 - 超好玩...
  15. #pragma DATA_SECTION的使用
  16. 《钢铁是怎样炼成的》的读后感作文5000字
  17. 【Visual C++】游戏开发笔记四十二 浅墨DirectX教程之十 游戏输入控制利器:DirectInput专场...
  18. Visio画图字体字号太小,默认8,如何设置默认更大字号
  19. Is there a way to enable UEFI support in KVM
  20. 【Flink】The parallelism of non parallel operator must be 1

热门文章

  1. 模仿游戏中图灵设计的计算机叫什么,智能哲学:“第三问题”与图灵的“模仿游戏”...
  2. 蛋花花分享互联网的赚钱方法
  3. 【ARM Cortex-M 系列 1 -- Cortex-M0, M3, M4, M7, M33 差异】
  4. 拆书帮第14期训练营——作业六:第一周复盘
  5. 地宫寻宝java_蓝桥杯 2014年 第五届 迷宫寻宝 详解(JAVA)
  6. 数据库SQL语句查询
  7. 开漏输出,推挽输出,开集输出
  8. python random randint_numpy.random.randint的详细用法 - python
  9. 用ts接第三方h5sdk时,简单书写第三方sdk的(.d.ts)声明文件
  10. echarts改变图例颜色形状icon的用法,和svg图片信息的了解