updateEngine升级

安卓 update_engine 启动机制深度解析:从属性触发到 Binder 就绪

1. 引言:为什么关注 update_engine 的启动?

在采用 A/B(无缝)更新 的安卓设备上,update_engine 是一个至关重要的守护进程。它负责在后台安全地下载、验证并应用系统更新,确保用户设备能够平滑升级。

与常规应用不同,update_engine 需要极高的权限来直接读写系统分区(如 bootsystemvendor)。因此,它的启动并非由应用框架层发起,而是由更底层的 init 进程在特定时机触发。理解其启动时序,对于深入掌握安卓系统启动流程、进行系统定制或排查OTA相关问题都至关重要。

2. 核心启动流程总览

简单来说,update_engine 的启动遵循一个清晰的链条:Bootloader -> Kernel -> Init(属性系统) -> 执行二进制 -> 注册Binder服务

下图描绘了这一完整流程的核心环节与时序:

Binderupdate_engine ServiceProperty SystemInit ProcessKernelBootloaderBinderupdate_engine ServiceProperty SystemInit ProcessKernelBootloader传递 cmdlineandroidboot.slot_suffix=_a启动 init解析内核 cmdline设置 ro.boot.slot_suffix=_a触发属性变更事件执行 start update_enginefork/exec/system/bin/update_engine注册服务android.os.UpdateEngineService注册完成,进入主循环

3. 详细启动时序与代码解析

阶段一:Init 进程与属性触发器

安卓用户空间的第一个进程是 init。它负责解析 .rc 配置文件来启动和管理服务。update_engine 的启动定义在一个典型的 update_engine.rc 文件中。

关键配置文件 (system/update_engine/update_engine.rc):

# update_engine.rc
service update_engine /system/bin/update_engine
    class main
    user root
    group root cache inet
    seclabel u:r:update_engine:s0
    disabled  # 关键:不随 class main 自动启动
    shutdown critical

    # 属性触发器:当系统属性 ro.boot.slot_suffix 被设置时启动
    on property:ro.boot.slot_suffix=*
        setprop update_engine.slot_suffix ${ro.boot.slot_suffix}
        start update_engine  # 启动服务的命令

解析

  • disabled:表明该服务不会在 class main 启动时自动运行。
  • on property:ro.boot.slot_suffix=*:这是一个属性触发器。它监听系统属性 ro.boot.slot_suffix。一旦该属性被设置(无论值是什么),触发器内的命令就会执行。
  • start update_engine:这是真正启动服务进程的命令。

阶段二:属性的起源与触发时机

那么,关键的 ro.boot.slot_suffix 属性从何而来?它源于 Bootloader

  1. Bootloader 传递:支持 A/B 分区的 Bootloader 在启动内核时,会通过内核命令行传递当前激活的槽位信息,例如 androidboot.slot_suffix=_a
  2. Init 解析并设置属性init 进程在早期的 on initon early-init 阶段,会调用 property_initprocess_kernel_cmdline 等函数来解析内核命令行。当它遇到 androidboot.slot_suffix 时,会将其转换为 ro.boot.slot_suffix 系统属性并设置。
  3. 触发器激活:属性被设置的瞬间,init 进程中监听此属性的触发器被激活,随即执行 start update_engine

阶段三:服务进程的执行与初始化

start 命令导致 init 进程 fork()exec() 执行 /system/bin/update_engine 这个 ELF 二进制文件。

程序入口 (system/update_engine/update_engine_main.cc):

int main(int argc, char** argv) {
    brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderr);
    auto update_engine_daemon = update_engine::UpdateEngineDaemon{};
    return update_engine_daemon.Run(); // 核心逻辑在此
}

守护进程初始化 (system/update_engine/common/update_engine_daemon.cc):
UpdateEngineDaemon::Run() 方法是核心,其主要逻辑如下:

int UpdateEngineDaemon::Run() {
    // 1. 初始化Binder框架
    auto binder_wrapper = AndroidBinderWrapper::Create();
    // 2. 创建核心业务对象(依赖HAL)
    auto system_state = std::make_unique<SystemState>(...);
    // 3. 实例化主服务对象
    main_service_ = new UpdateEngineService(std::move(system_state));
    // 4. 注册为Binder系统服务
    auto res = android::defaultServiceManager()->addService(
        android::String16("android.os.UpdateEngineService"),
        main_service_);
    // 5. 加入Binder线程池,等待调用
    android::IPCThreadState::self()->joinThreadPool();
    return 0;
}

至此,update_engine 服务已经启动完毕,并作为系统服务 android.os.UpdateEngineService 等待来自系统其他部分(如 SystemUpdateManager)的 Binder 调用。

4. 关键点与厂商定制差异

启动机制的核心特点

  • 精确触发:依赖 A/B 分区属性,确保只在支持的设备上启动。
  • 权限与隔离:以 root 权限运行在独立进程,通过 Binder 接口与外界通信,保证了安全边界。
  • 强依赖:依赖于 Bootloader 传递的正确槽位信息。

为什么我在源码里找不到?

重要提示:这是安卓开发中的常见困惑。标准路径 (system/update_engine/) 存在于 AOSP(Android开源项目)。但在实际设备(尤其是手机)的源码中,它很可能被厂商修改。

可能性说明查找建议
厂商深度定制代码被重命名、移动至 vendor/hardware/ 目录下,或完全被私有实现替换。使用 find . -name \"*update_engine*\" 全局搜索。
Android Mainline 模块化在更新版本的 AOSP 中,它可能被移至 packages/modules/update_engine/检查该路径。
源码不完整同步代码时未包含此仓库。检查 .repo/manifests 中的清单文件。

启动时序小结

整个启动过程可以概括为以下几个步骤:

  1. Bootloader 启动内核,并传递当前槽位信息。
  2. 内核 启动 init 进程。
  3. Init 解析内核命令行,设置 ro.boot.slot_suffix 属性。
  4. 属性触发器 被激活,执行 start update_engine
  5. Init 创建进程,执行 /system/bin/update_engine 二进制文件。
  6. update_engine 运行 main(),初始化后通过 UpdateEngineDaemon::Run() 注册 Binder 服务,进入主循环等待指令。

5. 总结

update_engine 的启动是安卓属性系统与 init 服务管理机制协同工作的一个典范。它展示了安卓如何通过简单的属性键值对,来精确控制一个高权限系统服务的生命周期。理解这个过程,不仅能帮助开发者深入系统底层,也为处理OTA更新、系统升级等高级任务打下了坚实基础。

下次当你研究系统启动优化,或者为设备移植A/B更新功能时,希望这篇分析能为你提供清晰的路线图。

你是否在定制ROM或研究系统启动时遇到过与update_engine相关的问题?欢迎在评论区分享你的经历和发现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

balance&&imbalance

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值