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分区布局示意图 物理分区:super (大小固定) system_a 逻辑分区 vendor_a 逻辑分区 product_a 逻辑分区 空闲空间(可分配给任意逻辑分区) 元数据区域(分区表信息、组信息) 逻辑分区可动态调整大小

你看,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 实战:如何安全地调整分区大小

我在项目中总结了一套安全调整分区的流程:

  1. 先用lpdump查看当前布局,确认空闲空间有多少。
  2. 计算目标大小:比如system要从2GB扩到2.5GB,那就需要空闲空间至少有512MB。
  3. 修改编译配置:更新BOARD_SUPER_PARTITION_SIZE(如果需要)和各分区大小。
  4. 重新编译并生成super.img
  5. 刷机验证:刷完后用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