当你点击手机上的 WiFi 热点名称,一个连接请求从 Java 层的
WifiManager.connect()出发,经过 Framework 状态机、AIDL HAL、C 守护进程、Netlink 内核接口,最终变成一帧 802.11 Auth 空中帧。这条路径跨越百万行级代码、5 层架构、2 大芯片平台。本文为你画出这张全景地图——告诉你每一层"是什么"、"为什么这么设计"、以及该按什么顺序读代码。注意:
WifiManager.connect()从 Android 10 起也已弃用,现代 Android 推荐使用WifiNetworkSuggestionsAPI。本文用connect()做入口纯粹是为了展示调用链的完整性,它的跨层追踪价值远大于它的 API 状态。
本章导读
本章比喻:WiFi 系统就像一家大型医院。App 是患者(提出需求),Framework 是门诊部(分诊、调度),Supplicant 是主治医师(做出诊断和治疗决策),HAL 是医疗器械标准(不管哪个品牌的 CT 机,接口都一样),Driver 是具体的医疗设备(高通的 CT 机和联发科的 MRI 机操作方式不同,但都遵循 HAL 标准),Firmware 是设备内部的嵌入式控制系统(你看不到源码,但设备靠它运转)。患者不需要知道 CT 机是哪个品牌的——这正是分层架构的意义。
你将学到:
•Android WiFi 全栈的 5 层架构及每层职责•为什么这样分层——每一层设计决策背后的技术理由•一次完整 WiFi 操作的跨层调用链•数据包从 App 到网卡的完整旅程•百万行级代码的阅读路线图
数据来源:AOSP(Wifi 模块、wpa_supplicant、HAL 接口)、QCOM(qcacld-3.0 驱动、wifi-host-cmn、cnss2 平台、QCOM HAL)、MTK(gen4m 驱动、conninfra、MTK HAL)。完整仓库链接见文末「代码来源说明」。
代码说明:本文代码片段为便于阅读经过精简和注释化处理,非逐字复制。完整实现请参考上述源码仓库。
一、5 层架构:为什么这样分?
Android WiFi 系统采用经典的分层架构,从上到下分为 5 层。Supplicant 和 HAL 虽然都是 native 层组件,但职责完全不同——Supplicant 是协议引擎(认证、密钥、漫游),HAL 是硬件抽象层(厂商适配),所以各自独立成层。
关于图中 HAL 与 Supplicant 的排序:配图按调用路径排列(Framework 通过 AIDL 分别调用 HAL 和 Supplicant,两者是同层级的并行组件),下方表格按职责分组排列(协议逻辑 → 硬件抽象)。两种排序都是正确的——取决于你是从"数据怎么流"还是"功能怎么分"的角度看。本文采用第二种分组方式。

| App / Framework | ||||
| Supplicant | ||||
| HAL | ||||
| Driver | ||||
| Firmware |
代码量计算方式:以 QCOM 平台为例,Framework ~293K + Supplicant ~669K + HAL ~140K + Driver ~323K ≈ 142 万行。加上 wpa_supplicant 工具/测试代码、以及 MTK 平台的独立驱动代码,总量超过 150 万行。
为什么这样分层?
这不是随意的设计,而是 Android 生态的必然选择:
WifiManager.startScan() | ||
IWifi/IWifiStaIface 等标准接口,芯片厂商只实现接口即可,类似 USB 标准 | ||
cfg80211_ops |
比喻:就像医院的分诊系统——患者(App)不需要知道哪台 CT 机是西门子还是 GE 的,门诊部(Framework)会根据病情分配到合适的科室,主治医师(Supplicant)做诊断,医疗器械(Driver+Firmware)执行检查。分层让每一层都可以独立替换和升级。
二、每一层长什么样?
2.1 App 与 Framework:用户看到的一切
用户与 WiFi 的所有交互都在这一层——打开开关、选择热点、查看连接状态。
// WifiManager.java — 用户的入口public boolean setWifiEnabled(boolean enabled) {return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);}
注意:
setWifiEnabled()从 Android 10(API 29)起已标记为@Deprecated。现代 Android 使用WifiNetworkFactory和NetworkRequest机制自动管理 WiFi 开关,而非用户手动控制。
WifiManager 是一个轻量级代理,通过 AIDL Binder 调用 system_server 中的 WifiServiceImpl。这是 Android 系统服务的标准模式。
Framework 层的核心组件:
ActiveModeWarden | ||
ClientModeImpl | ||
WifiConnectivityManager | ||
WifiScanningServiceImpl | ||
WifiNative |
深入阅读:ClientModeImpl 的 9 个状态(Disconnected → L2Connecting → L3Connected)和状态转移逻辑,详见 STA 连接专题(规划中)。
2.2 Supplicant:WiFi 的"大脑"
Supplicant 就是前文比喻中的主治医师——决定用什么认证方式、怎么握手、密钥怎么生成。
wpa_supplicant 是一个独立的 C 进程,负责 WiFi 的核心"医疗决策":
•扫描:决定扫哪些信道、用什么 SSID、主动还是被动•认证:执行 WPA/WPA2/WPA3/SAE/EAP 等认证协议•密钥管理:4-Way Handshake 生成 PTK/GTK,安装到驱动•漫游:BSS 选择、FT 快速漫游、BTM 响应
入口函数链:
// main() 中顺序调用 — wpa_supplicant/main.cmain()→ wpa_supplicant_init() // 初始化全局结构、加载驱动配置→ wpa_supplicant_add_iface() // 添加网络接口(wlan0)→ wpa_supplicant_run() // 注册信号处理、进入主循环→ eloop_run() // 事件循环(永不返回)
为什么是独立进程?
wpa_supplicant处理的协议非常复杂(WPA3-SAE 的 Dragonfly 密钥交换、EAP-TLS 的证书验证),放在用户空间可以用 gdb 调试、崩溃后重启不影响内核。代价是 EAPOL 帧的处理延迟——这也是 MTK 做 In-Driver Bridge 的原因(内核态处理 EAPOL,满足 50ms 重传 deadline)。
Supplicant 通过 wpa_driver_ops 函数表与驱动通信——这是一个经典的 C 语言"多态"设计:
// src/drivers/driver.h:3097 — 摘要,实际定义 100+ 个函数指针(视编译配置而定)struct wpa_driver_ops {int (*scan2)(...); // 触发扫描(802.11 MLME-SCAN)int (*associate)(...); // 发起关联(802.11 MLME-ASSOCIATE)int (*deauthenticate)(...); // 断开认证(802.11 MLME-DEAUTHENTICATE)int (*set_key)(...); // 设置加密密钥int (*get_scan_results)(...); // 获取扫描结果// ... 实际定义 100+ 个操作函数(视编译配置而定)};
为什么用函数表? 因为
wpa_supplicant需要支持多种驱动后端(NL80211、wext、test),每种后端实现不同的wpa_driver_ops。运行时根据配置选择具体实现,这就是 C 语言版的"接口抽象"。
2.3 HAL:Java 到内核的桥梁
HAL 是医疗器械标准——不管底层芯片是 QCOM 还是 MTK,Framework 只调用标准的
IWifi接口。
HAL(Hardware Abstraction Layer)是 Framework 和驱动之间的翻译层:

IWifi | |
IWifiChip | |
IWifiStaIface |
Android 12+ 使用 AIDL 替代 HIDL。AIDL 框架支持 in-process 模式(虽然当前 WiFi HAL 仍是独立进程),为未来的性能优化留出空间;此外 AIDL 的编译时类型检查更强,减少了接口版本不匹配的问题。
HAL 有两层:标准接口 + 厂商实现。
标准接口层(AOSP 提供):wifi_legacy_hal.cpp 定义了 wifi_hal_fn 函数表,包含 100+ 个标准操作(scan、connect、set_key 等)。这一层是"翻译官",把 AIDL 调用转成 C 函数调用。
厂商私有 HAL 层(芯片厂商提供):每个厂商实现 init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) 函数,填充函数表。内部通过 nl80211(Netlink) + ioctl(SIOCDEVPRIVATE+1 发送 vendor 命令、SIOCGIFFLAGS/SIOCGIFHWADDR 管理接口属性)与内核驱动通信。
AIDL HAL (标准接口)→ wifi_legacy_hal.cpp (封装层, 调用 wifi_hal_fn)→ 厂商私有 HAL (实现 wifi_hal_fn)→ nl80211 Netlink → 内核驱动
加载方式:wifi_legacy_hal_factory.cpp 先尝试 dlsym(RTLD_DEFAULT, "init_wifi_vendor_hal_func_table") 找静态链接的符号;找不到则从 /vendor/etc/wifi/vendor_hals/*.xml 读取 .so 路径,通过 dlopen 动态加载。
// wifi_legacy_hal_factory.cpp — 两种加载方式// 方式 1: 静态链接(符号已在进程中)initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT, "init_wifi_vendor_hal_func_table");// 方式 2: 动态加载 .so(path 来自 /vendor/etc/wifi/vendor_hals/*.xml 配置文件)void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);initfn = (init_wifi_vendor_hal_func_table_t)dlsym(h, "init_wifi_vendor_hal_func_table");
QCOM 和 MTK 的实现对比:
hardware/qcom/wlan/qcwcn/wifi_hal/ | hardware/mediatek/wlan/wifi_hal/ | |
wifi_hal.cpp | wifi_hal.cpp | |
cld80211_lib) | cpp_bindings) | |
.so | .so |
关键理解:AIDL HAL 是"合同"(定义了接口),厂商私有 HAL 是"执行"(实现了接口)。两者都通过 nl80211 + ioctl 与内核驱动通信——nl80211 处理标准 WiFi 操作(扫描、连接),ioctl(
SIOCDEVPRIVATE+1、WEXTSIOCIWFIRSTPRIV+N)处理厂商私有命令和接口管理。区别在于各自支持的 vendor 命令和扩展功能不同。Framework 层不知道也不关心底层是 QCOM 还是 MTK。
wificond:HAL 层还有一个容易被忽略的组件——wificond(WiFi C++ Daemon)。它是一个独立的 C++ 守护进程,位于 HAL 和内核 nl80211 之间,负责扫描调度和接口管理。Framework 通过 WifiNl80211Manager 与 wificond 通信(Binder IPC),wificond 再通过 nl80211 与内核 cfg80211 交互。与 vendor HAL 不同,wificond 是 AOSP 提供的标准组件,所有厂商共用。
深入阅读:HAL 层的 HIDL → AIDL 演进、HalDeviceManager 接口管理、Nl80211Proxy 新路径,详见第二章《Framework 与 HAL》。
2.4 内核驱动:两大平台,两种哲学
前面三层(Framework、Supplicant、HAL)是 AOSP 统一的,所有厂商共享。从驱动开始,高通和联发科各走各路——医疗设备(驱动)内部构造完全不同,但都遵循 HAL 标准(同样的操作接口)。这是最复杂的一层。
深入阅读:QCOM 的 wlan_objmgr 对象模型、CM 状态机、WMI 握手,以及 MTK 的 AIS FSM、conninfra 电源域管理,详见第三章《驱动加载与崩溃恢复》。
2.5 Firmware:你看不到的黑盒
固件是设备内部的嵌入式控制系统——你看不到源码,但设备靠它运转。
固件运行在 WiFi 芯片内部的独立处理器上,源码不公开。但驱动通过标准接口与它通信:
| QCOM | WMI_CMD,固件回 WMI_EVENT | |
| MTK |
固件的职责:
•射频控制:信道切换、功率调整、天线选择•帧过滤:硬件层过滤不需要的帧(如非本 BSSID 的 Beacon),减少 CPU 负担•功耗管理:DTIM 省电、TWT(Target Wake Time)•硬件扫描:PNO 扫描由固件独立执行,CPU 可以休眠•密钥安装:PTK/GTK 安装到硬件加密引擎,数据帧在芯片内完成加密/解密•漫游辅助:802.11k 邻居报告、802.11r FT 快速漫游的部分帧交换
驱动与固件的通信通过 WMI(WLAN Management Interface)协议:驱动发送 WMI 命令(如 WMI_START_SCAN_CMDID),固件执行后通过 WMI 事件(如 WMI_SCAN_EVENTID)上报结果。所有 WMI 消息都通过 HIF(Host Interface)传输层封装——QCOM 通过 PCIe 上的复制引擎(Copy Engine)传输,MTK 通过 MCR 寄存器(WFDMA 机制)传输。
固件崩溃(assert)时的恢复流程:驱动检测到固件无响应 → 触发 SSR(SubSystem Restart)→ 重新下载固件 → 重建连接。详见 STA 打开专题。
三、一次完整的操作:从点击到数据包
3.1 连接的跨层调用链
以 STA 连接到一个 WPA2 热点为例——一次完整的跨层流程:

App 层: WifiManager.connect()→ Framework 层: ClientModeImpl.connectToNetwork() // 状态机调度→ Supplicant 层: SupplicantStaIfaceHalAidlImpl.connectToNetwork() // AIDL 跨进程桥接→ wpa_supplicant 选择认证方式、触发关联→ Driver 层: NL80211_CMD_CONNECT → cfg80211 → 厂商驱动→ 空中: Auth → Assoc → EAPOL 4-Way Handshake → DHCP
深入阅读:连接流程的每一步(ClientModeImpl 状态机、3 种认证方式、NL80211 双路径、四次握手、DHCP),详见 STA 连接专题(规划中)。
3.2 数据包的旅程:从 App 到网卡
连接建立后,数据包的路径:

发送路径:App 调用 socket.send() → 内核协议栈(TCP → ip_output() → Netfilter POST_ROUTING → ip_finish_output2() 路由+邻居解析 → dev_queue_xmit())→ WiFi 驱动 ndo_start_xmit() → DMA 到芯片 → 802.11 帧封装 → 射频发送。
接收路径:WiFi 芯片 → DMA → 驱动 RX 中断 → netif_receive_skb() → 内核协议栈反向解封装(ip_rcv() → Netfilter PRE_ROUTING → ip_local_deliver() → TCP → Socket → App)。
关键理解:WiFi 驱动在内核中注册为一个网络设备(
net_device),和有线网卡一样走标准的ndo_start_xmit()接口。上层协议栈(TCP/IP/Netfilter)完全不知道下面是有线还是无线——这正是 Linux 网络子系统的分层设计。
WiFi 特有的内核路径:
•cfg80211:管理无线配置(扫描、连接、密钥),通过 nl80211 与用户空间通信•mac80211:SoftMAC 设备的 802.11 帧管理(Android WiFi 驱动多为 FullMAC,不经过 mac80211)•Netfilter:防火墙规则,Android 的流量统计和防火墙在这里实现
四、代码阅读路线图
面对百万行级代码,建议按以下顺序阅读:
第一阶段:建立全局观(1-2 天)
1.本文(架构总览)2.各仓库的 README / Android.bp
第二阶段:自顶向下(3-5 天)
1.WifiServiceImpl.java - 理解 WiFi 服务入口2.ClientModeImpl.java - 理解 STA 状态机3.WifiNative.java - 理解 JNI 桥接4.SupplicantStaIfaceHalAidlImpl.java - 理解 HAL 调用
第三阶段:深入 Supplicant(3-5 天)
1.wpa_supplicant/main.c - 入口2.wpa_supplicant/wpa_supplicant.c - 核心逻辑3.wpa_supplicant/scan.c - 扫描调度4.wpa_supplicant/sme.c - SAE/EAP 认证5.wpa_supplicant/ctrl_iface.c - 控制接口
第四阶段:驱动层(5-10 天)
QCOM 路线:
1.wlan_hdd_main_module.c - 模块入口2.wlan_hdd_main.c - HDD 核心3.wlan_objmgr_psoc_obj.c - 理解对象模型4.wlan_cm_sm.c - CM 状态机5.qca-wifi-host-cmn/wmi/ - WMI 通信
MTK 路线:
1.conninfra/connv2_drv.c - conninfra 初始化入口(conninfra 仓库)2.wlan_drv_init.c → gl_init.c - WLAN 模块入口(触发 wlanProbe)3.wlan_lib.c - wlanAdapterStart4.ais_fsm.c - AIS 状态机(最重要)5.saa_fsm.c - SAA 状态机
五、本系列导航
每篇文章自包含,讲完一个完整主题。可按任意顺序阅读。
六、总结
Android WiFi 的 5 层架构是 10 年演进的结果。就像患者不需要知道 CT 机是西门子还是 GE 的,App 也不需要知道底层是 QCOM 还是 MTK——这正是分层架构的价值。每一层的存在都有明确的技术理由:
•Framework 让 App 不关心硬件差异•Supplicant 把复杂协议放在用户空间,方便调试和升级•HAL 让芯片厂商只需实现标准接口•Driver 把硬件差异封装在内核中•Firmware 把实时性要求高的操作下沉到芯片
下一章,我们将从最底层开始——驱动是如何加载的?固件是如何下载的?从
insmod wlan.ko到 WiFi 芯片就绪,中间经历了什么?
代码来源说明
本文分析的代码来自以下公开仓库,读者可自行下载查阅:
AOSP:
•packages/modules/Wifi[1] - Android WiFi Mainline 模块•external/wpa_supplicant_8[2] - WPA Supplicant•hardware/interfaces/wifi[3] - HAL 接口定义
Qualcomm:
•vendor-qcom-opensource-wlan-qcacld-3.0[4] - QCOM 主驱动•vendor-qcom-opensource-wlan-qca-wifi-host-cmn[5] - 公共主机库•vendor-qcom-opensource-wlan-platform[6] - 平台驱动(cnss2/icnss2)•hardware_qcom_wlan[7] - QCOM WiFi HAL
MediaTek:
•kernel_modules-connectivity-wlan-core-gen4m[8] - MTK 主驱动•kernel_modules-connectivity-conninfra[9] - 连接基础设施•hardware_mediatek/wlan[10] - MTK WiFi HAL
所有代码均为开源项目。本文中的代码分析基于 Android 16 (API 36) 版本。
References
[1] packages/modules/Wifi:https://android.googlesource.com/platform/packages/modules/Wifi/[2]external/wpa_supplicant_8:https://android.googlesource.com/platform/external/wpa_supplicant_8/[3]hardware/interfaces/wifi:https://android.googlesource.com/platform/hardware/interfaces/[4]vendor-qcom-opensource-wlan-qcacld-3.0:https://github.com/nicklela21/vendor-qcom-opensource-wlan-qcacld-3.0[5]vendor-qcom-opensource-wlan-qca-wifi-host-cmn:https://github.com/nicklela21/vendor-qcom-opensource-wlan-qca-wifi-host-cmn[6]vendor-qcom-opensource-wlan-platform:https://github.com/nicklela21/vendor-qcom-opensource-wlan-platform[7]hardware_qcom_wlan:https://github.com/nicklela21/hardware_qcom_wlan[8]kernel_modules-connectivity-wlan-core-gen4m:https://github.com/nicklela21/vendor-mediatek-kernel_modules-connectivity-wlan-core-gen4m[9]kernel_modules-connectivity-conninfra:https://github.com/nicklela21/vendor-mediatek-kernel_modules-connectivity-conninfra[10]hardware_mediatek/wlan: https://github.com/nicklela21/hardware_mediatek
夜雨聆风