WifiService 启动流程:SystemServer 加载、构造函数、注册系统服务

各位同学,今天我们来聊聊 WifiService 的启动流程。说实话,这部分代码我翻来覆去看了不下二十遍。每次系统启动卡在 Wi-Fi 上,最后定位问题都绕不开这里。你想想看,一个 Wi-Fi 功能从系统开机到真正能用,中间经历了什么?今天我们就把它彻底拆开。

一、SystemServer 里的“第一声啼哭”

Android 系统启动时,Zygote 进程孵化出 SystemServer。SystemServer 就像个大管家,负责启动各种系统服务。WifiService 就是其中之一。

具体入口在哪?在 SystemServer.javarun() 方法里。它会调用 startOtherServices(),然后一路走到 Wi-Fi 相关的启动代码。我贴一段核心代码,你感受一下:

// frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    // ... 前面启动了很多服务
    t.traceBegin("StartWifi");
    try {
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_WIFI)) {
            // 创建 WifiService 实例
            wifi = new WifiService(context);
            // 注册到 ServiceManager
            ServiceManager.addService(Context.WIFI_SERVICE, wifi);
        }
    } catch (Throwable e) {
        reportWtf("starting WifiService", e);
    }
    t.traceEnd();
    // ... 后面还有别的服务
}

嗯,这里要注意一个细节:hasSystemFeature 检查。如果设备硬件不支持 Wi-Fi,这段代码根本不会执行。我在项目中遇到过一款平板,硬件明明有 Wi-Fi 芯片,但系统编译时没加 FEATURE_WIFI,结果 Wi-Fi 服务压根没启动。排查了半天,最后发现是产品配置问题。

二、WifiService 构造函数:初始化那些事儿

构造函数里做了哪些事?说白了,就是为 Wi-Fi 服务准备好“家当”。我直接上代码:

// frameworks/base/wifi/java/android/net/wifi/WifiService.java

public class WifiService extends SystemService {
    private final WifiServiceImpl mImpl;
    private final WifiContext mWifiContext;

    public WifiService(Context context) {
        super(context);
        // 创建 WifiContext,封装了系统上下文
        mWifiContext = new WifiContext(context);
        // 创建真正的实现类
        mImpl = new WifiServiceImpl(mWifiContext);
    }
}

你看,构造函数本身很轻量。它没有直接去打开 Wi-Fi 硬件,也没有加载驱动。为什么?因为系统服务启动是有顺序的。如果一上来就操作硬件,其他依赖的服务(比如电源管理、网络管理)可能还没准备好。我个人习惯把这种“延迟初始化”叫做“懒加载”,Android 框架里到处都是这种设计。

这里有个关键点:WifiServiceImpl 才是真正干活的类。构造函数里只是创建了它,但没调用任何初始化方法。真正的初始化,要等到系统服务注册完成、系统进入 BOOT_COMPLETED 阶段才会触发。

核心要点:WifiService 构造函数只做两件事——创建 WifiContext 和 WifiServiceImpl。不碰硬件,不启动线程,不注册广播。保持构造函数轻量,是系统服务设计的黄金法则。

三、注册系统服务:让世界知道“我来了”

回到 SystemServer 的代码:

ServiceManager.addService(Context.WIFI_SERVICE, wifi);

这行代码干了什么?它把 WifiService 实例注册到 ServiceManager 中。ServiceManager 是一个全局的服务注册表。任何进程想用 Wi-Fi 服务,都得通过 Context.getSystemService(Context.WIFI_SERVICE) 来获取。而 ServiceManager 就是那个“中介”。

注册完成后,WifiService 的 onBootPhase() 方法会被系统回调。这个方法定义了服务在不同启动阶段的行为:

@Override
public void onBootPhase(int phase) {
    if (phase == PHASE_SYSTEM_SERVICES_READY) {
        // 系统服务就绪,可以初始化 Wi-Fi 状态机了
        mImpl.checkAndStartWifi();
    } else if (phase == PHASE_BOOT_COMPLETED) {
        // 系统完全启动,可以处理用户交互了
        mImpl.handleBootCompleted();
    }
}

我曾经踩过一个坑:在 PHASE_SYSTEM_SERVICES_READY 之前就去调用 Wi-Fi 的 enable 方法,结果返回了 false。为什么?因为状态机还没初始化,底层 HAL 还没连接。所以,理解启动阶段非常重要。

避坑指南:如果你在开发系统应用,想确保 Wi-Fi 服务可用,不要监听 ACTION_BOOT_COMPLETED 就立刻操作 Wi-Fi。建议监听 WifiManager.WIFI_STATE_CHANGED_ACTION,等状态稳定了再动手。

四、整体流程可视化

说了这么多,我画了一张图帮你理清思路。这张图展示了从 SystemServer 到 WifiService 启动的完整链路:

WifiService 启动流程 SystemServer startOtherServices() Feature 检查 hasSystemFeature(WIFI) WifiService 构造函数 注册服务 ServiceManager.addService() onBootPhase() PHASE_SYSTEM_SERVICES_READY 关键阶段说明 1. SystemServer 启动 2. 检查 Wi-Fi Feature 3. 创建 WifiService 实例 4. 注册到 ServiceManager 5. 回调 onBootPhase() 6. 初始化状态机 注意:构造函数不操作硬件,真正的初始化在 onBootPhase() 中触发

五、注册后的“连锁反应”

服务注册完成后,系统会通过 Binder 机制把 WifiService 暴露给其他进程。这时候,任何应用调用 getSystemService(WIFI_SERVICE) 都能拿到一个 Binder 代理。但这个代理能干什么?取决于 WifiServiceImpl 暴露了哪些接口。

我整理了一张表,列出注册前后系统状态的变化:

阶段 WifiService 状态 外部可调用? 硬件状态
构造函数完成 对象创建,未初始化 否(未注册) 未操作
注册到 ServiceManager 已注册,可被获取 是,但返回空或异常 未操作
PHASE_SYSTEM_SERVICES_READY 状态机初始化 是,基础功能可用 加载 HAL
PHASE_BOOT_COMPLETED 完全就绪 是,全部功能可用 可扫描/连接

你看,注册服务只是“挂号”,真正能看病还得等医生上班。这个“医生”就是 onBootPhase() 回调。

注意:千万不要在 WifiService 的构造函数里做耗时操作。SystemServer 启动是有超时机制的。如果某个服务构造函数执行超过 5 秒,系统会直接重启。我见过有人把网络请求写在构造函数里,结果设备无限重启。嗯,那场面相当壮观。

六、总结一下

WifiService 的启动流程,说白了就是三步走:

  1. SystemServer 加载:在系统服务启动阶段,检查设备是否支持 Wi-Fi,然后创建 WifiService 实例。
  2. 构造函数:轻量初始化,只创建核心对象,不碰硬件。
  3. 注册系统服务:把实例注册到 ServiceManager,等待后续阶段回调完成真正初始化。

这个流程设计得很巧妙。它把“服务可用”和“服务就绪”分开了。服务注册后,其他进程可以拿到引用,但真正干活要等系统准备好。这种分层思想,在 Android 系统服务里随处可见。

好了,这一节就到这里。记住这张流程图和那张状态表,后面讲 WifiServiceImpl 初始化的时候,你会回来感谢我的。


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