安卓第三方ROM制作:super格式解包打包全流程实操指南
简介:动态分区机制已成为现代安卓系统分区管理的核心方案,它将system、vendor、product等逻辑分区统一封装在super镜像中。理解这一底层结构,是进行ROM定制、系统精简或集成root的前提。借助lpunpack与lpmake等AOSP工具链,开发者可以完整地解包super容器,修改分区内容后重新打包生成可刷入镜像。这一能力不仅支撑第三方ROM制作,也广泛应用于系统级优化、预装应用清理、内核替换等工程场景。从原始固件提取、稀疏镜像转换,到AVB校验处理和刷机包组装,每一步都需要对格式细节有清晰认知。本文以实操视角,梳理基于super格式的安卓解包打包全流程,帮助读者规避常见坑点,快速产出可用的定制ROM。 搞第三方ROM这件事,说难不难,说简单也真不简单。2022年之后,安卓的动态分区方案基本普及,以前那种直接拿system.img扔进刷机包的时代已经过去了,现在解包打包绕不开super格式。这篇文章我就把这一整套东西捋清楚:从工具选型、环境准备,到解包、修改、重打包、刷入,全程实操记录,该踩的坑都给你标出来。无论你是想精简系统、集成root,还是想给老机型做第三方适配,这份流程都能直接抄作业。
1. 为什么要折腾解包打包:先搞懂你要面对的是什么
1.1 第三方ROM工作流的起点
做第三方ROM,第一步永远是拿到官方固件,然后把它拆开,改成你想要的样子,再重新封装成可刷入的格式。这里的核心矛盾在于:安卓系统如今不是一个单一的镜像,而是被拆成了system、vendor、product、odm等多个分区,每个分区又通过动态分区机制被塞进了一个叫做super的大容器里。你要改动系统文件,就得先穿透super这层壳。
所以标题里说的“支持super格式解包打包”,恰恰是2022年以后做ROM绕不开的基础能力。以前的机型直接在system分区里改东西,system.new.dat.br这种压缩格式也是老玩家熟悉的形态;现在新机型几乎都是动态分区,super镜像一出来,很多旧工具直接失灵,这就逼着工具链迭代。
1.2 动态分区到底改变了什么
动态分区设计的初衷是让厂商在OTA升级时更灵活地调整分区大小,不用像以前那样预留死板的空间。但对ROM制作者来说,它带来了两个直接影响:第一,你没法直接把super当普通镜像挂载,它是一个逻辑卷容器,真正的分区数据是按system、vendor等逻辑分区塞在里面的;第二,重打包时分区大小不是随便定的,要基于原始分区大小做合理调整,否则刷入后系统分区空间不足,开机就崩。
理解这一点,你就能明白为什么工具链必须更新换代。过去的“解包→改→打包”三板斧,现在变成了“解super→解逻辑分区→改→重打逻辑分区→重打super→重打刷机包”的更长链路。每一步都有对应的工具和参数,少一环都走不通。
1.3 这套工具解决的典型场景
- 精简系统:去掉厂商预装的一堆全家桶,删掉用不上的内置应用,释放系统空间。
- 集成root:把Magisk补丁打进
boot分区镜像,刷完就是已root状态。 - 替换内核:给设备换上第三方内核,提升性能或续航。
- 做本地化适配:把海外版固件中的部分组件替换成国内版,或者反过来。
- 制作卡刷包:把解包后修改的内容重新封装成可刷入的zip包,分享给其他人。
如果你属于以上任何一种场景,下面这套流程就是为你准备的。
2. 开工前的准备:工具选型和环境搭建
2.1 环境选择:Windows还是Linux
解包打包工具链里,很多核心工具是Linux优先的。虽然Windows也有移植版,但兼容性问题会让你多踩很多坑。我的建议是:主力操作在Linux下完成,Windows用户开一个WSL或者虚拟机,体验会顺畅很多。
Ubuntu 22.04是我实测下来最稳的环境。需要注意一点:工具链依赖的某些库文件版本不能太新也不能太旧,Ubuntu 22.04的glibc版本对大多数预编译工具来说都是友好的。Debian系的其他版本也问题不大,但如果你用Arch这种滚动更新的发行版,偶尔会遇到预编译工具因为glibc版本过高而运行报错的情况。
2.2 核心工具清单
| 工具 | 用途 | 备注 |
|---|---|---|
payload-dumper-go | 解包payload.bin格式的OTA/全量包 | Go语言写的高效解包器,速度远快于Python版 |
lpunpack | 解包super.img中的逻辑分区 | AOSP构建工具链的一员 |
lpmake | 将逻辑分区重新打包成super.img | AOSP构建工具链的一员 |
simg2img | 将稀疏镜像转换为可挂载的原始镜像 | 处理厂商ROM的常见前置步骤 |
img2simg | 将原始镜像转换为稀疏镜像 | 打包时按需使用 |
mke2fs | 创建ext4文件系统镜像 | 需要指定-t ext4 |
resize2fs | 调整ext4镜像文件大小 | 打包前扩展镜像空间用 |
Android Image Kitchen | 解包/重打包boot.img | 处理内核与ramdisk |
magiskboot | 直接给boot.img打补丁 | Magisk工具链自带,处理root更自动化 |
这些工具里,lpunpack和lpmake是核心中的核心。它们没有对应的Windows官方版,Linux下是最稳的。如果不想自己编译,GitHub上能找到不少预编译版本,但一定要核对来源,这种工具经常被恶意篡改,建议优先从AOSP源码编译,或者从长期维护的开源项目里获取二进制。
2.3 镜像获取:从官方固件开始
做第三方ROM的原料来源,主要是厂商官方固件。你需要找到对应机型的最新全量包,注意是全量刷机包,而不是增量OTA包。增量包里的payload.bin只包含改动过的部分,解包出来的分区镜像往往不完整,不适合拿来修改。
全量包的特征是:包体一般较大,包含完整的payload.bin或super.img。官网下载的线刷包一般解压后能看到images目录,里面有各种分区镜像和脚本;卡刷包则是一个zip,里面大概率就是payload.bin加一个META-INF目录。
下载固件时注意核对机型代号和版本号,刷错机型的固件轻则变砖,重则丢失IMEI或传感器校准数据。这个坑我见过太多次,后面会专门讲。
3. 解包实战:从刷机包到可修改分区
3.1 第一步:识别你的刷机包格式
拿到固件后,先解压看结构。常见三种情况:
- 目录里有
super.img或super.img.sparsechunk.*:这是线刷包格式,直接用lpunpack解。 - 目录里只有一个
payload.bin:这是卡刷包/OTA包格式,先用payload-dumper-go解出super.img或分区镜像。 - 目录里有
system.new.dat.br加vendor.new.dat.br:这是老的A-only分区的压缩格式,需要专门的dat工具链处理,属于旧设备场景。
2022年之后的机型基本都是前两种。先按这个判断流程走,能省掉很多摸索时间。
3.2 从payload.bin解出super
用payload-dumper-go解包payload.bin,一条命令就能搞定:
payload-dumper-go payload.bin默认会在当前目录下生成一个extracted文件夹,里面是super.img加上boot.img、dtbo.img等非动态分区镜像。如果你的目标是做常规系统精简,解到这一步就够了。
如果你只想提取其中某个分区,也可以加参数指定,比如只解system:
payload-dumper-go -partitions system payload.bin这里有个小技巧:payload.bin解包出来的super.img是稀疏镜像格式,体积看起来很小,这是正常的,不要以为文件损坏。后续要用lpunpack处理它,或者先用simg2img转换成原始镜像再挂载,视你的具体需求而定。
3.3 用lpunpack解开super容器
现在的关键步骤,把super.img里的逻辑分区都掏出来:
lpunpack super.img output_dir/lpunpack会根据super镜像头部的几何信息,自动识别并解出system、vendor、product、odm等所有逻辑分区。执行完之后,output_dir里就是一个个独立的稀疏镜像文件。
注意:解出来的分区镜像绝大多数也是稀疏格式的,如果你打算直接挂载修改,先转换:
simg2img system.img system.raw.img这样拿到手的system.raw.img才是真正的ext4文件系统镜像,可以直接用mount挂载,或者先用fsck.ext4检查文件系统完整性,再挂载:
mkdir -p mnt/system sudo mount -o loop system.raw.img mnt/system/挂载之后,mnt/system目录下就是你熟悉的安卓系统文件结构:app、priv-app、framework、etc等等。这时候,你想删什么就删什么,想加什么就加什么。
3.4 处理boot.img:root和内核修改
如果你要集成root或者替换内核,boot.img也要解包处理。用Android Image Kitchen是最直观的方式:
./unpackimg.sh boot.img它会生成split_img(内核、dtb等)和ramdisk(根文件系统)两个目录。如果只是集成Magisk,更推荐直接用magiskboot:
magiskboot unpack boot.img magiskboot patch boot.imgmagiskboot会处理好ramdisk的修补与vp2签名校验等问题,比手动改省心得多。但如果你要替换内核,还是得用Android Image Kitchen,把split_img里的Image.gz(或Image)替换成新编译的内核文件,再重新打包。
4. 修改与重打包:把改动重新封装成可刷镜像
4.1 常见修改场景
到这里你面对的是一个可随意改写的系统文件树。我实操里最常见的三类修改:
- 精简预装:删除掉你不需要的apk。注意,
priv-app下的应用权限很高,有些系统组件删了会导致系统服务起不来,别乱删。吃不准的先查包名和依赖关系,宁可不删也别让系统崩掉。 - 添加功能:把apk放到
system/app或system/priv-app下,设置好权限(644)和属主(root:root),重启后就会出现在系统里。要注意targetSdkVersion和系统版本兼容性,高版本apk放到低版本系统里经常crash。 - 修改配置:改动
build.prop、mixer_paths.xml这类配置文件,实现解锁全局高采样率、调整屏幕密度等操作。
个人建议:改动的每一步都做记录,方便出问题时回溯。直接改系统文件不是不能改,但要带着“科学实验”的心态,一次只改一类内容,打包刷机后逐项验证。
4.2 重新打包system分区镜像
修改完文件系统后,第一步是把改动重新封装成ext4镜像。这里不能用之前的稀疏镜像直接回写,因为文件增删会导致镜像大小和inode数量变化,正确做法是用mke2fs重新生成一份ext4镜像,再往里面写文件。
在修改完成后的system.raw.img基础上,先扩展镜像空间:
resize2fs system.raw.img 3G然后再动态调整文件系统内部inode和块大小,这一步主要是为了给新增文件预留空间。如果你知道要增加的文件总大小,也可以直接计算:
# 当前文件系统已用空间为1.8G,新增文件0.5G,则目标镜像至少2.5G resize2fs system.raw.img 2500M扩展完成并确认文件系统没有损坏后(顺手fsck.ext4 -f检查一遍),用img2simg把它转换成稀疏镜像,方便后续存进super容器:
img2simg system.raw.img system.img注意:super容器内部的分区大小和分区块大小都要跟镜像实际内容匹配,lpmake在打包时会根据你指定的分区大小生成逻辑卷,分区大小留多了浪费空间,留少了刷机后分区空间不足一样会出问题。
4.3 用lpmake重新生成super镜像
lpmake是AOSP里提供的一个工具,用来把多个逻辑分区打包成super镜像。核心命令长这样:
lpmake --metadata-size 65536 --super-name super --metadata-slots 2 \ --device super:4294967296 \ --group main:4294967296 \ --partition system:readonly:2147483648:main \ --partition vendor:readonly:1073741824:main \ --partition product:readonly:1073741824:main \ --output super_new.img \ --sparse参数说明:
--metadata-size:元数据区大小,一般65536够用。--metadata-slots 2:美团分区元数据默认有两个槽位,建议和原镜像保持一致。--device super:总大小:super分区总字节数,要与原设备分区大小一致。一般可以从原super.img头部的几何信息里读出来,或者通过lpunpack --geometry查看。--group main:总大小:逻辑分区组大小,一般和super总大小一致。--partition 名称:属性:大小:组:列出每个逻辑分区的名字、权限、大小与归属组。readonly属性是系统分区的常规设置。
如果你不确定分区大小,最稳的办法是用原始super.img的信息:
lpunpack --geometry super.img这个命令会把super镜像中的分区几何信息输出,照着填lpmake参数就行。
打包完成后得到super_new.img,如果是用--sparse生成的,刷机时直接传给fastboot也能识别,但我建议在正式刷机前回读一下分区表,确认逻辑分区没有错位:
lpunpack --debug super_new.img temp_check/能正常解出来且文件大小与你配置的分区大小一致,就说明结构没问题。
4.4 处理boot.img:打包和校验
如果你动过boot.img(无论是集成root还是换内核),打包时也要同步处理。
对于Android Image Kitchen,修改完ramdisk和内核后回到工具目录,执行:
./repackimg.sh生成的新boot.img会在当前目录下,文件名一般叫image-new.img。对于Magisk补丁过的,magiskboot unpack之后,如果你没有额外修改ramdisk,直接执行:
magiskboot repack boot.img就能得到一份包含Magisk补丁的新boot.img。
打包boot.img前,建议先校验一下文件是否完整。Android Image Kitchen在打包时会检查内核是否为空、ramdisk是否有效,但不会检查内核和设备的硬件匹配度。如果解包的是boot.img但机型不对,打包后强刷大概率变砖。
4.5 组装刷机包
有了新的super_new.img和boot_new.img,最后一步是组装成可刷机的形式。两种常见方式:
- 线刷方式:把
super_new.img、boot_new.img放到官方线刷包对应的images目录,覆盖掉原文件,然后运行刷机脚本,或者手动用fastboot flash super super_new.img和fastboot flash boot boot_new.img。 - 卡刷方式:把
payload.bin重新生成,payload-dumper-go有rebuild功能,但参数复杂,我一般直接用payload-dumper-go解压后手动替换,再用zip命令打包,注意保持META-INF目录原样。
卡刷包生成有个细节:系统分区的AVB校验必须处理,否则刷入后无法开机。这是动态分区方案绕不开的坑,下面专门讲。
5. 常见问题排查与避坑实录
5.1 问题速查表
| 问题现象 | 大概率原因 | 解决办法 |
|---|---|---|
lpunpack解包失败 | super.img是稀疏镜像或者几何信息损坏 | 先simg2img super.img super.raw.img,再lpunpack |
lpmake打包后刷机提示分区不存在 | --partition名称与设备预期不一致 | 对照原镜像的几何信息,确保名称完全一致 |
| 刷机后卡第一屏或循环重启 | boot.img未正确处理,或AVB校验失败 | 检查boot.img,或关闭AVB,再重新打包 |
| 系统分区空间不足 | 打包时--partition大小设置过小 | 重新用lpmake,把分区大小调大 |
| 精简后某些系统功能异常 | 删除了不必要的系统组件 | 恢复被删的包,或先冻结观察 |
| 刷机后IMEI丢失或基带异常 | 刷入了非对应机型的固件 | 不要强行刷入不匹配机型的固件,及时刷回官方救砖 |
5.2 AVB验证的坑
动态分区方案普遍启用AVB(Android Verified Boot),它会对super、boot、vbmeta等镜像做哈希校验。如果你修改了system分区但没有相应的AVB签名更新,刷完后会直接提示系统损坏,无法开机。
解决办法有两种:
第一种是修改vbmeta镜像,把验证关掉。vbmeta.img一般在刷机包里独立存在,处理方式是用工具把vbmeta的flags位改成2,或者把vbmeta清空。我用的命令行:
avbtool make_vbmeta_image --flags 2 --output vbmeta_new.img刷机时把vbmeta_new.img替换进刷机包或单独刷入。
第二种是只关闭system分区的AVB,不动vbmeta。这个操作隐蔽一些,在vbmeta.img中指定不需要验证的分区即可,但这依赖厂商的AVB结构,不同设备差异较大,建议直接使用方式一,通用性好。
需要注意的是,关闭AVB意味着系统不再校验完整性,如果你刷入的ROM本身存在恶意代码,设备安全性会下降。仅做测试和自用时问题不大,但别拿别人的ROM关掉AVB再用,风险自负。
5.3 稀疏镜像与原始镜像的混淆
这是新手最容易踩的坑。super.img是稀疏镜像,system.img也可能是稀疏镜像,但它们不能直接混用。
- 从
super里解出来的system.img是稀疏格式,挂载前必须先simg2img。 - 重新打包
super时,内部放的是稀疏或原始格式都可以,lpmake都能处理。 - 刷机时
fastboot flash system system.img,如果你的system.img是稀疏格式,fastboot会自动识别,但如果你的包内super结构不对,fastboot会报Invalid sparse file format。
实操中,我会把system.img保持在稀疏格式用于打包,但挂载修改时一定转成原始镜像。一句话总结:修改用原始镜像,封装用稀疏镜像。
5.4 payload.bin重新生成的问题
如果你的发布渠道是卡刷包,就一定要面对重新生成payload.bin的问题。最省心的方式是:解包出的super_new.img和boot_new.img,再配合一个未改动的payload.bin,计算出差异后再封包。但payload的上游工具链bug不少,生成出来的包经常出现哈希不匹配。
我的做法更简单粗暴:放弃重新生成payload,直接出线刷包。把super_new.img和boot_new.img放进官方线刷包的images目录,去掉原有的payload.bin,刷机时直接fastboot刷写。问题是你必须确保用户设备解锁了bootloader,而且知晓刷机风险。
如果非要卡刷包,还有一条路:把super_new.img和boot_new.img用payload-dumper-go的repack命令封进payload.bin,再配上原META-INF目录一起打包。这个方法依赖工具对哈希表的重算,实测下来速度快,但兼容性没有线刷包稳。
5.5 关于厂商安全机制
还有一个绕不开的现实问题:不少厂商会在ROM完整性校验之外,再叠加一层自己的检测逻辑。如果你的目标是刷入第三方ROM后又想保留官方系统服务,大概率会被拦截,报错信息五花八门,有的提示当前ROM异常,有的直接拒绝某些功能。
我的态度很明确:做第三方ROM是技术探索,但不要想方设法绕过厂商的安全机制。改了系统还要求享受官方系统级服务的完整性保护,本质上就跟“门锁换了还想用原配钥匙”一样矛盾。把改动控制在自用和开源的LSPosed、Magisk生态里,大家玩得都开心。
6. 实操心得:这套流程在当前机型上的表现
最后聊几句个人体会。这套解包打包流程我在多个机型上跑过,包括小米系的几款、一加的高通机型、还有个别MTK设备。整体流程上,高通机型的super解析是最干净的,lpunpack和lpmake兼容性最好;MTK机型偶尔会在lpunpack阶段报错,多数是因为厂商在super里塞了非标准元数据,可以用--metadata-size参数调整尝试,再不行就手动提取逻辑分区。
小米系机型要特别注意:官方线刷包里的super.img可能存在分区命名与AOSP标准不完全一致的情况,比如多了xiaomi相关的逻辑分区。打包时如果不把这个分区也加进去,刷机后系统可能无法启动。解决办法是解包时完整记录所有逻辑分区名称,打包时全部映射。
一加机型的高通设备有个好处:payload.bin的解包结果非常规整,动态分区大小基本合理,不用做太多调整就能直接重打包。如果你是第一台练手机,建议从一加或者Pixel这类“干净”的设备开始,少踩很多坑。
另外说一下Windows用户:就算你有WSL,fastboot刷机命令尽量还是在Windows的原生环境跑,WSL下的USB直通偶尔会出现设备识别不稳定的问题。解包打包在Linux里做,刷机在Windows原生控制台里做,分工明确,效率最高。
这套流程我大概每两个月就要跑一遍,现在基本能做到“拿到固件30分钟内出第一个可刷包”。工具链本身不难,难的是对格式细节的把握和对设备特性的理解。多刷几台机器,多踩几次坑,你就知道为什么super格式的解包打包工具一定要顺手了。
本文还有配套的精品资源,点击获取
