10、动态分区技术:super分区布局、lpdump与lpmake工具、分区表管理与调整
动态分区,说白了就是Android系统里的一块“弹性存储池”。
我记得刚接触这个技术时,心里还挺犯嘀咕的——以前分区都是死的,system多大、vendor多大,编译时就定死了。后来发现,这种静态分区太不灵活了。你想想看,system多塞了点东西,vendor那边空着一大半,但你就是挪不过来。动态分区就是来解决这个问题的。
10.1 super分区是什么?
super分区,就是动态分区的“容器”。它本身是一个物理分区,里面装着好几个“逻辑分区”。比如system、vendor、product、odm这些,现在都变成了super里面的逻辑分区。
我习惯把super分区想象成一个“大箱子”。箱子本身有固定的尺寸,但里面的隔板可以自由移动。你往system里多放点东西,它就撑大一点;vendor用不上了,就缩一缩。嗯,这就是动态分区的核心思想。
关键点:super分区的大小,在编译时由BOARD_SUPER_PARTITION_SIZE决定。所有逻辑分区的总和,不能超过这个值。
10.2 分区布局:一张图看懂
我画了一张图,帮你快速理解super分区的内部结构:
你看,super分区里除了各个逻辑分区,还有一块“空闲空间”。这块空间就是用来动态调整的。system不够了,就从空闲里划一块过去;vendor多了,就还回去。
10.3 lpdump工具:查看分区表
lpdump,全称是“logical partition dump”。说白了,就是用来查看super分区里都有啥的。
我在项目中经常用它来排查问题。比如OTA升级后,发现某个分区大小不对,第一件事就是跑一下lpdump看看。
基本用法:
# 查看当前系统的super分区布局
lpdump
# 查看指定镜像文件的分区表
lpdump super.img
# 输出详细信息(包含组信息、分区属性等)
lpdump -d super.img
输出示例:
Slot 0 (current):
Partition system_a:
Size: 2048 MB
Attributes: readonly
Group: google_dynamic_partitions
Partition vendor_a:
Size: 512 MB
Attributes: readonly
Group: google_dynamic_partitions
Partition product_a:
Size: 1024 MB
Attributes: readonly
Group: google_dynamic_partitions
Group google_dynamic_partitions:
Maximum size: 4096 MB
Free space: 512 MB
小技巧:如果你在设备上跑lpdump发现没有输出,可能是权限问题。记得先adb root,或者用su切换到root用户。
10.4 lpmake工具:制作super镜像
lpmake,就是用来“造”super镜像的。编译系统时,会把各个分区的镜像文件(比如system.img、vendor.img)打包成一个super.img。
我个人习惯在调试时手动跑lpmake,这样能精确控制每个分区的大小。
基本用法:
lpmake \
--device-size 4294967296 \ # super分区总大小(4GB)
--metadata-size 65536 \ # 元数据区域大小
--metadata-slots 2 \ # 元数据槽位数(AB系统需要2个)
--group google_dynamic_partitions \
--partition system_a:readonly:2147483648:google_dynamic_partitions \
--partition vendor_a:readonly:536870912:google_dynamic_partitions \
--partition product_a:readonly:1073741824:google_dynamic_partitions \
--image system_a=out/system.img \
--image vendor_a=out/vendor.img \
--image product_a=out/product.img \
--output super.img
这里要注意几个参数:
- --device-size:必须和BOARD_SUPER_PARTITION_SIZE一致,否则刷机会报错。
- --metadata-slots:AB系统一般设为2,非AB系统设为1。
- --group:分区组,所有逻辑分区必须属于某个组。组的大小限制了所有分区总和。
我曾经踩过的坑:有一次我改了分区大小,但忘了更新--device-size。结果刷机后设备直接变砖,进不了系统。后来用fastboot刷回原厂镜像才救回来。所以,改分区大小一定要同步更新device-size!
10.5 分区表管理与调整
分区表管理,说白了就是“增删改查”super里的逻辑分区。
Android提供了lpdump、lpmake、lpadd、lpremove、lpresize等工具。不过在实际项目中,我们最常用的还是lpdump和lpmake。
为什么?因为动态分区表在设备运行时是只读的。你想改分区大小?得重新生成super.img,然后刷进去。
不过,有一种情况例外——OTA升级。OTA脚本可以在更新时动态调整分区大小。比如:
# OTA脚本中调整分区大小
resize_logical_partition system_a 3072M
resize_logical_partition vendor_a 768M
嗯,这里要注意:OTA调整分区时,必须保证所有分区总和不超过super总大小。否则升级会失败。
10.6 实战:如何安全地调整分区大小
我在项目中总结了一套安全调整分区的流程:
- 先用lpdump查看当前布局,确认空闲空间有多少。
- 计算目标大小:比如system要从2GB扩到2.5GB,那就需要空闲空间至少有512MB。
- 修改编译配置:更新BOARD_SUPER_PARTITION_SIZE(如果需要)和各分区大小。
- 重新编译并生成super.img。
- 刷机验证:刷完后用lpdump确认分区大小是否正确。
核心原则:调整分区大小,本质上是“重新分配空闲空间”。只要总和不超,就不会有问题。
10.7 避坑指南
最后,分享几个我踩过的坑:
- 元数据空间不足:metadata-size设得太小,会导致分区表写不进去。建议至少64KB。
- 组大小限制:所有分区总和不能超过组的maximum size。我见过有人只改了分区大小,忘了改组大小,结果编译报错。
- AB系统双份:system_a和system_b都要占空间。你给system_a分了2GB,system_b也得留2GB。所以实际可用空间只有super总大小的一半。
- 刷机顺序:刷super.img时,一定要用fastboot flash super super.img,不要用fastboot flash system system.img。否则动态分区表会被破坏。
嗯,动态分区技术其实不复杂。你只要记住:super是个大箱子,逻辑分区是里面的隔板,空闲空间就是可调整的余地。掌握了lpdump和lpmake这两个工具,大部分问题都能搞定。
公众号:蓝海资料掘金营,微信deep3321