二、A/B 升级update_engine分析-整体模块

update_engine简介 近期猛然发现公司的项目都已经换成了AB升级,AB升级之前一直有所了解,只是一直都没有去仔细查看过其具体升级流程,这两天捋了捋,简单整理下。 AB升级(谷歌官网叫法无缝更新)是自android7.0开始新增的一种android设备升级方式,只是这种方式对设备存储要求高,所以之前没有怎么被国内手机厂商采用。 简而言之:系统同时存在两套system分区,一套处于休眠状态不可使用,一套处于使用状态,两者通过slot的概念来做区分,在设备启动引导阶段通过特殊标记位确定启动哪个system,当有可用升级版本时候,客 阅读详情
AI摘要

本文详细剖析了AB Update机制下的update_engine模块,包括其编译流程、关键组件及依赖关系,重点介绍了update_engine_client和update_engine服务端进程,为理解Android系统级OTA升级提供了深入视角。

    调试通了AB后确实想好好整理下这部分,其实与传统ota对比,我个人这样划分1、bootloder部分 2、kernel部分 3、framwork部分 4、update_engine核心 5、升级包的制作,而其中的大部分工作都来源于核心update_engine,在这里卡了很久,决定先从这里入手,按照framwork---->(binder机制)update_engine流程(设定对应的值给到boot_control)---->bootloder--->kernel---->ramdisk--->Android这样分析,本次先着重分析update_engine模块,我个人觉得对于目前分析问题,思路对于工作越来越重要,工作中问题形形色色,千奇百怪,有一套自己的方法处理起来才能得心应手。

    system/update_engine/的代码量比较多,首先我们先从Android.mk分析,这都是比较好的习惯,例如我们分析可执行文件和py文件从main方法入手一样,Android.mk代码比较多,先分割模块

总体模块

一、控制变量设定

二、编译参数设定和依赖定义

三、update_metadata-protos模块编译

四、libpayload_consumer模块编译

五、libupdate_engine_boot_control模块编译

六、libupdate_engine模块编译

七、libupdate_engine_android模块编译

八、update_engine模块编译

九、update_engine_sideload模块编译

十、update_engine_client模块编译

十一、libpayload_generator模块编译

十二、delta_generator模块编译

十三、Private and public keys for unittests.

十四、Sample images for unittests.

十五、update_engine.conf

十六、test_http_server

十七、test_subprocess

十八、update_engine_unittests

十九、Update payload signing public key.

二十、Brillo update payload generation script

 

看起来是挺多的,20个需要分析的,不过里面有部分并不会用到,下面我们开始挖坑分析

 

一、控制变量设定

 

# Default values for the USE flags. Override these USE flags from your product
# by setting BRILLO_USE_* values. Note that we define local variables like
# local_use_* to prevent leaking our default setting for other packages.
#USE标志的默认值。 覆盖产品中的这些USE标志
#通过设置BRILLO_USE_ *值。 请注意,我们定义了局部变量,例如
#local_use_ *以防止泄漏其他软件包的默认设置
local_use_binder := $(if $(BRILLO_USE_BINDER),$(BRILLO_USE_BINDER),1)
local_use_hwid_override := \
    $(if $(BRILLO_USE_HWID_OVERRIDE),$(BRILLO_USE_HWID_OVERRIDE),0)
local_use_mtd := $(if $(BRILLO_USE_MTD),$(BRILLO_USE_MTD),0)
local_use_chrome_network_proxy := 0
local_use_chrome_kiosk_app := 0

# IoT devices use Omaha for updates.
local_use_omaha := $(if $(filter true,$(PRODUCT_IOT)),1,0)
    
#log for local_use_*  这里是我加的打印,变量不清楚就打印出来看
#system/update_engine/Android.mk:35: warning: "local_use_binder = 1"
#system/update_engine/Android.mk:36: warning: "local_use_hwid_override = 0"
#system/update_engine/Android.mk:37: warning: "local_use_mtd = 0"
#system/update_engine/Android.mk:38: warning: "local_use_chrome_network_proxy = 0"
#system/update_engine/Android.mk:39: warning: "local_use_chrome_kiosk_app = 0"
#system/update_engine/Android.mk:46: warning: "local_use_omaha = 0"
    
$(warning "local_use_binder = $(local_use_binder)")  
$(warning "local_use_hwid_override = $(local_use_hwid_override)")
$(warning "local_use_mtd = $(local_use_mtd)")
$(warning "local_use_chrome_network_proxy = $(local_use_chrome_network_proxy)")
$(warning "local_use_chrome_kiosk_app = $(local_use_chrome_kiosk_app)")
$(warning "local_use_omaha = $(local_use_omaha)")

这些变量定义好,用于下面各模块的编译控制

local_use_binder = 1

local_use_hwid_override = 0

local_use_mtd = 0

local_use_chrome_network_proxy = 0

local_use_chrome_kiosk_app = 0

local_use_omaha = 0

二、编译参数设定和依赖定义

 

#定义一些编译的规则
ue_common_cflags := \
    -DUSE_BINDER=$(local_use_binder) \
    -DUSE_CHROME_NETWORK_PROXY=$(local_use_chrome_network_proxy) \
    -DUSE_CHROME_KIOSK_APP=$(local_use_chrome_kiosk_app) \
    -DUSE_HWID_OVERRIDE=$(local_use_hwid_override) \
    -DUSE_MTD=$(local_use_mtd) \
    -DUSE_OMAHA=$(local_use_omaha) \
    -D_FILE_OFFSET_BITS=64 \
    -D_POSIX_C_SOURCE=199309L \
    -Wa,--noexecstack \
    -Wall \
    -Werror \
    -Wextra \
    -Wformat=2 \
    -Wno-psabi \
    -Wno-unused-parameter \
    -ffunction-sections \
    -fstack-protector-strong \
    -fvisibility=hidden
ue_common_cppflags := \
    -Wnon-virtual-dtor \
    -fno-strict-aliasing
ue_common_ldflags := \
    -Wl,--gc-sections
#定义依赖
#c文件依赖
ue_common_c_includes := \
    $(LOCAL_PATH)/client_library/include \
    system
#动态库依赖
ue_common_shared_libraries := \
    libbrillo-stream \
    libbrillo \
    libchrome
#静态库依赖
ue_common_static_libraries := \
    libgtest_prod \

三、update_metadata-protos模块编译

# update_metadata-protos (type: static_library)
# ========================================================
# Protobufs.
ue_update_metadata_protos_exported_static_libraries := \
    update_metadata-protos
ue_update_metadata_protos_exported_shared_libraries := \
    libprotobuf-cpp-lite

ue_update_metadata_protos_src_files := \
    update_metadata.proto

# Build for the host.编译host静态库
include $(CLEAR_VARS)
LOCAL_MODULE := update_metadata-protos
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_IS_HOST_MODULE := true
generated_sources_dir := $(call local-generated-sources-dir)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(generated_sources_dir)/proto/system
LOCAL_SRC_FILES := $(ue_update_metadata_protos_src_files)
LOCAL_CFLAGS := -Wall -Werror
include $(BUILD_HOST_STATIC_LIBRARY)

# Build for the target.编译target静态库
include $(CLEAR_VARS)
LOCAL_MODULE := update_metadata-protos
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
generated_sources_dir := $(call local-generated-sources-dir)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(generated_sources_dir)/proto/system
LOCAL_SRC_FILES := $(ue_update_metadata_protos_src_files)
LOCAL_CFLAGS := -Wall -Werror
include $(BUILD_STATIC_LIBRARY)

定义静态库update_metadata-protos,分别指向host和target环境

protobuf是google团队开发的用于高效存储和读取结构化数据的工具。什么是结构化数据呢,正如字面上表达的,就是带有一定结构的数据。比如电话簿上有很多记录数据,每条记录包含姓名、ID、邮件、电话等,这种结构重复出现。

xml、json也可以用来存储此类结构化数据,但是使用protobuf表示的数据能更加高效,并且将数据压缩得更小,大约是json格式的1/10,xml格式的1/20。

四、libpayload_consumer模块编译

# libpayload_consumer (type: static_library)
# ========================================================
# The payload application component and common dependencies.
# payload应用程序组件和通用依赖项。
ue_libpayload_consumer_exported_static_libraries := \
    #包含了update_metadata-protos 所以先编译update_metadata-protos静态库,再编译libpayload_consumer
    update_metadata-protos \
    libxz \
    libbz \
    libbspatch \
    libbrotli \
    libpuffpatch \
    $(ue_update_metadata_protos_exported_static_libraries)
ue_libpayload_consumer_exported_shared_libraries := \
    libcrypto \
    $(ue_update_metadata_protos_exported_shared_libraries)

ue_libpayload_consumer_src_files := \
    common/action_processor.cc \
    common/boot_control_stub.cc \
    common/clock.cc \
    common/constants.cc \
    common/cpu_limiter.cc \
    common/error_code_utils.cc \
    common/file_fetcher.cc \
    common/hash_calculator.cc \
    common/http_common.cc \
    common/http_fetcher.cc \
    common/hwid_override.cc \
    common/multi_range_http_fetcher.cc \
    common/platform_constants_android.cc \
    common/prefs.cc \
    common/subprocess.cc \
    common/terminator.cc \
    common/utils.cc \
    payload_consumer/bzip_extent_writer.cc \
    payload_consumer/cached_file_descriptor.cc \
    payload_consumer/delta_performer.cc \
    payload_consumer/download_action.cc \
    payload_consumer/extent_reader.cc \
    payload_consumer/extent_writer.cc \
    payload_consumer/file_descriptor.cc \
    payload_consumer/file_descriptor_utils.cc \
    payload_consumer/file_writer.cc \
    payload_consumer/filesystem_verifier_action.cc \
    payload_consumer/install_plan.cc \
    payload_consumer/mount_history.cc \
    payload_consumer/payload_constants.cc \
    payload_consumer/payload_metadata.cc \
    payload_consumer/payload_verifier.cc \
    payload_consumer/postinstall_runner_action.cc \
    payload_consumer/xz_extent_writer.cc

ifeq ($(HOST_OS),linux)
# Build for the host.
include $(CLEAR_VARS)
LOCAL_MODULE := libpayload_consumer
LOCAL_MODULE_CLASS := STATIC_LIBRARIES
LOCAL_CPP_EXTENSION := .cc
LOCAL_CFLAGS := $(ue_common_cflags)
LOCAL_CPPFLAGS := $(ue_common_cppflags)
LOCAL_LDFLAGS := $(ue_common_ldflags)
LOCAL_C_INCLUDES := \
    $(ue_common_c_includes)
LOCAL_STATIC_LIBRARIES := \
    update_metadata-protos \
    $(ue_common_static_libraries) \
    $(ue_libpayload_consumer_exported_static_libraries) \
    $(ue_update_metadata_protos_exported_static_libraries)
LOCAL_SHARED_LIBRARIES := \
    $(ue_common_shared_libraries) \
    $(ue_libpayload_consumer_exported_shared_libraries) \
    $(ue_update_metadata_protos_exported_shared_libraries)
LOCAL_SRC_FILES := $(ue_libpayload_consumer_src_files)
include $(BUILD_HOST_STATIC_LIBRARY)
endif  # HOST_OS == lin
android9.0 A/B system使用SD卡升级流程 主要涉及的模块: recovery,A/B system下recovery进程调用update_engine_sideload可执行程序进行升级。 update_engine_sideload,调用bootcontrol服务设置AB系统状态 bootcontrol服务 update_verifier服务 设备进入recovery模式调用update_engine_sideload的流程: bs... 阅读详情

相关推荐

Android OTA升级失败?手把手教你排查ErrorCode::kPostinstallRunnerError (5)等常见错误

本文针对Android OTA升级过程中常见的ErrorCode::kPostinstallRunnerError (5)等错误码,提供了系统性的排查指南。文章深入解析了OTA升级的核心流程与错误码体系,并手把手教你如何通过分析update_engine日志、检查分区状态及验证设备兼容性来定位和解决升级失败问题,帮助开发与运维人员快速恢复设备升级。

vim8coder的博客 790

Android P update_engine分析(四) --update_engine_client的工作

当AB系统升级时,有两种方式来调用updateengine,来实现升级,一种方法是直接执行shell命令,调用 update_engine_client,带参数来实现升级,另一种方式是应用层直接调用UpdateEngine的applyPayload方法来升级。 update_engine_client 带参升级 shell命令调用update_engine_client带参数去升级,具体如下: update_engine_client --payload=file:///sdcard/payload.bin

tovey2008的专栏 6636

Android A/B system - update_engine(一)

Android A/B System的升级过程是怎样的?理解这一过程就需要理解update_engine的逻辑。 首先来看main.cc,main.cc主要做了这些事: log相关 初始化crc-32 table 调用update_engine_daemon.Run() /system/update_engine/main.cc int main(int argc, char** argv) ...

Dufre 2895

Android A/B升级实战:从update_engine模块拆解到避坑指南

本文深入拆解了Android A/B升级的核心模块update_engine,详细剖析了libpayload_consumer、libupdate_engine_android等静态库的功能与依赖关系,并提供了从编译配置到实战调试的完整避坑指南,帮助开发者高效解决升级过程中的常见问题。

weixin_28365523的博客 170

Android OTA升级方案对比:Recovery与AB升级的机制、选型与避坑

设备出厂后如何安全高效地更新系统,是每个终端产品都必须面对的核心问题。OTA升级(Over The Air Update)通过网络下发系统更新包,由设备自行完成校验与写入,从而在不影响用户使用的前提下完成系统迭代。围绕这一目标,业界演化出两种主流路线:传统Recovery升级依赖独立恢复环境离线刷写,实现简单但升级期间系统不可用;而AB升级则通过双分区无缝切换,实现后台更新与失败自动回滚,大幅提升用户体验。Android 10后引入的动态分区与虚拟AB进一步降低了双分区带来的存储开销。两种方案在分区结构、流

weixin_29195615的博客 271

跨平台OTA升级框架设计:兼容高通、MTK、展锐的统一方案

OTA(空中升级)技术是嵌入式与物联网设备实现远程固件更新的核心机制,其原理是通过无线网络下载并安全刷写新固件,以修复漏洞、增强功能并延长产品生命周期。该技术的核心价值在于提升设备可维护性、保障系统安全并优化用户体验。在工程实践中,面对高通(Qualcomm)、联发科(MTK)和展锐(Unisoc)等不同芯片平台的**分区布局**、底层刷写接口和启动流程的显著差异,构建统一的OTA解决方案成为关键挑战。本文聚焦于通过**平台抽象层(PAL)** 与插件化架构,将通用的升级流程、安全校验与状态管理逻辑,与各平

weixin_30698527的博客 320

模块化笔记本成Linux开发者理想之选:可升级、可维护、自由掌控

开发者如何选择开发设备,常受操作系统、硬件升级能力与长期维护成本影响。Linux 环境对硬件兼容性尤为敏感,传统笔记本内存焊死、网卡驱动异常等问题往往令人困扰。模块化设计通过标准化接口,让内存、硬盘、无线网卡可自由更换,将 Linux 自由组合的哲学延伸至硬件层,大幅降低适配门槛与维修成本。对比 MacBook Pro 的一体化封闭生态,模块化笔记本在可扩展性和可维护性上优势显著,更符合追求设备长期主义的工程师需求。结合 Ubuntu 22.04 实例,展示从硬件检查、系统安装到 Node.js、Docke

weixin_30861797的博客 377

Android OTA差分升级全链路解析:从差分包生成到设备端落地

OTA升级是Android设备系统维护的关键技术,差分升级通过算法对比新旧镜像生成增量补丁,可将全量包压缩至5%-15%。其核心价值在于降低带宽消耗与升级成本,但在生成链路、分区写入、签名校验、状态机等环节带来更高复杂度。理解bsdiff/imgdiff选型、payload双层校验及A/B分区策略,是Android系统开发者设计可靠升级方案的基础。该技术广泛应用于智能硬件、车机、机顶盒等需要远程修复的IoT设备。从工程实践角度梳理从构建机生成差分包到设备端安装落地的完整链路与常见陷阱,可帮助开发者规避变砖风

weixin_29185167的博客 257

Ubuntu系统下STM32开发环境搭建:从零配置CubeMX、VSCode与OpenOCD调试实战

本文详细介绍了在Ubuntu系统下搭建STM32开发环境的完整流程,包括CubeMX、VSCode和OpenOCD的安装配置。通过实战教程指导开发者从基础环境准备到工程创建与调试,提供高效的嵌入式开发解决方案,并分享常见问题解决方法。

potato的博客 941

OpenDRIVE车道计算避坑指南:为什么你的poly3曲线总对不齐?

本文深入解析OpenDRIVE标准中车道几何计算的三大核心难题:参数化三次多项式(ParamPoly3)的坐标系转换与参数映射、车道偏移与宽度的优先级判定,以及螺旋线(Spiral)接续的平滑性保障。通过实战案例与代码示例,提供了一套避免车道线错位与曲率不连续的精确计算与验证方法,是高精地图开发与仿真场景构建的实用避坑指南。

q9w8e7r6t5的博客 424

QST QMC5883L —— 经典磁传感器的生存指南与替代预案

本文聚焦于QST旗下经典三轴磁力计 QMC5883L,解析其技术渊源、核心特性及当前面临的停产风险。结合真实应用场景提供续命方案与选型建议,为依赖该芯片的开发团队争取过渡时间窗口期。文章包含实测数据对比、生命周期管理策略及潜在替代方案拆解。存续价值判断✔️ 现有产品设计无需大幅改动即可延续生命;❌ 新项目采用将面临更高的维护成本;⚠️ 建议在6个月内完成技术路线切换。#磁传感器 #嵌入式开发 #供应链管理 #QST #QMC5883L。

2501_93066786的博客 998

LVGL按键触发回调函数的完整流程

如果是我的话我会怎么写:例如按键,我先定义一个结构体里面包含ID,事件名等和回调函数的链表节点结构体里面有具体函数的指针,也有指向下一个回调函数的链表节点的指针,初始化一个结构体变量的,通过BSP层来驱动触摸屏幕,再通过中间层与被按下时就会判断是长按还是短按还是其他,改变变量的事件例如:改成长按,生成事件包后再注册你长按的回调函数链表节点,再根据变量的事件到链表中遍历最后实现功能.父容器监听所有子列表项的点击事件,无需为每个列表项单独注册回调。的回调,打印所有事件日志,观察事件触发顺序。

solomonzw的博客 3239

Navicat从入门到精通:数据库管理全攻略

本文系统梳理Navicat数据库管理工具的核心应用体系。从基础的安装与多类型数据库连接入手,详解数据库与数据表的创建、修改、删除等操作逻辑;深入数据增删改查的可视化与 SQL 语句双重操作模式,结合Excel/SQL文件的导入导出场景提供实操指南。同时覆盖数据备份恢复、跨库同步等进阶功能,以及视图、存储过程等高级应用。通过对比同类工具突出Navicat的易用性与功能性优势,并针对连接失败、字符乱码等常见问题提供解决方案,帮助读者从零基础掌握数据库全生命周期管理,提升数据操作效率与安全性。

邓邓子的博客 1897

要理解成本中心与利润中心的根本区别与适用场景,需从 “责任范围、考核核心、管理目标” 三个核心维度切入,同时明确二者在企业管理体系中的联动关系

摘要: 成本中心与利润核心区别在于责任范围、考核目标和管理权限。成本中心仅对成本负责(如生产、行政部门),考核成本控制能力;利润中心需同时管控成本与收入(如独立产品线、区域分公司),以利润为核心指标。选择标准取决于单元是否拥有收入决策权:无收入权的支持/执行部门设为成本中心,能独立经营、核算盈亏的单元设为利润中心。二者协同运作,成本中心为利润中心提供基础支持,利润中心的需求动态影响成本中心资源配置,共同实现企业整体目标。划分本质是确保考核指标与责任范围匹配,避免管理失效。

金牌架构师 657

MediaPipe 教程:从安装到应用-全网最全

MediaPipe是Google推出的开源框架,专为构建机器学习管道设计,可以高效处理视频、音频等时间序列数据。本文教程从安装到应用逐步讲解: 安装步骤简单,只需通过pip安装mediapipe包并验证版本; 重点演示人体姿态检测功能,可识别33个身体关键点; 提供基础代码实现,包括视频捕获、关键点检测与可视化; 强调模块化开发,将功能封装成类以提高代码复用性。 教程适合初学者,通过清晰指引和实用代码示例,帮助快速实现计算机视觉应用。

FJN110的博客 1563

Qt —— 调用海康C++版SDK获取摄像头每帧图像,通过OpenCv处理每帧图像后显示在Qt窗口(附:源码)

  关注 笔者 - jxd 微信公众号搜索 “码农总动员” 或 微信扫描下方二维码,了解更多你不知道的XX,O(∩_∩)O

5447

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

上一篇: block格式差分包合并方法解析
下一篇: 一、A/B升级之系统image的生成
李标标
博客等级 码龄11年 124粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值