一、Wi-Fi 基础与框架概览:Android Wi-Fi 架构、WifiManager 与 WifiService 的关系、AIDL 接口定义

各位同学,咱们今天正式开讲 Wi-Fi 实战的第一课。说实话,我当年刚接触 Android Wi-Fi 时,也被那一堆 Service、Manager、Binder 搞得晕头转向。但别怕,今天我就带你把这些概念彻底捋清楚。

1.1 Android Wi-Fi 整体架构

Android 的 Wi-Fi 架构,说白了就是一套分层设计。从最上层的 App,一路穿透到最底层的硬件驱动。我习惯把它分成四层来看:

  • 应用层:你的 App 通过 WifiManager 发起请求
  • 框架层:WifiService 处理请求,管理状态机
  • HAL 层:Wi-Fi HAL 与内核驱动交互
  • 内核层:真正的 Wi-Fi 芯片驱动

你想想看,当你在手机上点一下「连接 Wi-Fi」,背后发生了多少事?

核心要点:整个 Wi-Fi 架构的核心是「服务端-客户端」模式。WifiManager 是客户端,WifiService 是服务端。它们通过 Binder 机制通信。

下面这张图,是我特意为你画的架构全景图。建议你多看几遍,后面所有内容都围绕它展开。

Android Wi-Fi 架构分层图 应用层 App (Settings / 第三方应用) → 调用 WifiManager API 框架层 WifiService (SystemServer) ←→ WifiManager (通过 AIDL / Binder) HAL 层 wpa_supplicant / Wi-Fi HAL (vendor 实现) 内核层 Wi-Fi 芯片驱动 (cfg80211 / mac80211) 用户空间 Java 框架 Native 层 内核空间

1.2 WifiManager 与 WifiService 的关系

这两个东西,是 Wi-Fi 开发里最核心的一对搭档。我刚开始做 Wi-Fi 功能时,总以为 WifiManager 就是干活的。后来才发现,它只是个「传话筒」。

我的经验:WifiManager 是你在 App 里能直接 new 出来的对象。但它内部其实持有一个 IWifiManager 的 Binder 代理。你调用的每个方法,最终都会通过 Binder 驱动,跑到 SystemServer 进程里的 WifiService 去执行。

举个例子,你调用 wifiManager.startScan(),流程是这样的:

  1. WifiManager 把请求打包成 Binder 事务
  2. Binder 驱动把数据传到 SystemServer
  3. WifiService 收到请求,调用底层扫描
  4. 结果再原路返回

说白了,WifiManager 就是个「遥控器」,WifiService 才是真正的「电视机」。

角色 所在进程 职责
WifiManager App 进程 提供 API,封装 Binder 调用
WifiService SystemServer 实际执行 Wi-Fi 操作,管理状态机
IWifiManager AIDL 接口 定义跨进程通信契约

避坑指南:我曾经在项目里直接拿 WifiManager 的实例做全局变量,结果 App 被杀后重新创建,WifiManager 里的 Binder 代理就失效了。记住,WifiManager 不能跨进程缓存,每次使用前最好重新获取。

1.3 AIDL 接口定义

AIDL,全称 Android Interface Definition Language。它存在的意义,就是让两个进程能「说同一种语言」。

WifiService 对外暴露的接口,就定义在 IWifiManager.aidl 里。我带你看看核心方法:

// IWifiManager.aidl (简化版)
interface IWifiManager {
    // 获取已配置的网络列表
    List<WifiConfiguration> getConfiguredNetworks();
    
    // 发起扫描
    boolean startScan(in ScanSettings settings, in IWifiScanner listener);
    
    // 连接指定网络
    void connect(in WifiConfiguration config, in IActionListener listener);
    
    // 断开当前连接
    void disconnect();
    
    // 获取连接信息
    WifiInfo getConnectionInfo();
    
    // 注册回调,监听 Wi-Fi 状态变化
    void registerWifiCallback(in IWifiCallback callback);
}

你注意看,这里有个关键点:in 关键字。它表示参数是从客户端流向服务端。如果是 out,则相反。双向就用 inout

核心理解:AIDL 接口就是 WifiManager 和 WifiService 之间的「合同」。双方都按这个合同来,谁也别耍赖。我在做系统定制时,经常需要扩展这个接口,比如加一个 setWifiPowerMode() 方法。这时候就要同时改 AIDL 文件、WifiService 实现、还有 WifiManager 的封装。

说到回调,IWifiCallback 也是通过 AIDL 定义的。WifiService 通过它把扫描结果、连接状态变化推送给 App。这其实就是观察者模式在跨进程场景下的应用。

// IWifiCallback.aidl
interface IWifiCallback {
    // 扫描结果可用
    void onScanResultsAvailable();
    
    // Wi-Fi 状态变化
    void onWifiStateChanged(int state);
    
    // 连接状态变化
    void onConnectionStateChanged(int state, in WifiInfo wifiInfo);
}

嗯,这里要注意:回调接口里的方法,都是在 Binder 线程池里执行的。你不能在里面做耗时操作,也不能直接更新 UI。我见过有同事直接在回调里弹 Toast,结果 App 直接崩溃——因为 Binder 线程没有 Looper。

我的建议:在 App 层收到回调后,用 Handler 切回主线程再处理 UI 更新。或者用 LiveData / RxJava 做线程切换,这样更优雅。

最后,我总结一下今天的内容。Wi-Fi 架构的核心就三件事:

  • 分层:App → Framework → HAL → Kernel
  • 通信:WifiManager 通过 AIDL/Binder 调用 WifiService
  • 回调:WifiService 通过 IWifiCallback 把结果推给 App

你把这些搞懂了,后面学 Wi-Fi 扫描、连接、热点等功能,就会轻松很多。下一节我们深入 Wi-Fi 扫描的流程,到时候我会拿一个真实项目里的坑来给你讲。


公众号:蓝海资料掘金营,微信 deep3321