和縣網(wǎng)站制作杭州seo排名費用
我在 《Android 動態(tài)分區(qū)詳解(二) 核心模塊和相關(guān)工具介紹》 介紹過 lpmake 工具,這款工具用于將多個分區(qū)鏡像打包生成一個 Android 專用的動態(tài)分區(qū)鏡像,一般稱為 super.img。Android 編譯時,系統(tǒng)會自動調(diào)用 lpmake 并傳入相關(guān)參數(shù)來生成 super.img,不需要我們手動操作。但難免還是有朋友想深入研究下 super.img,希望自己手動生成 super.img。所以這里專門開一篇詳解介紹下 lpmake 工具。
本文基于 android-13.0.0_r41 編譯生成的 lpmake 介紹該工具的使用,但也適用于 Android 10(Q) 開始的其它 Android 版本。
《Android OTA 相關(guān)工具》系列,目前已有文章列表:
- 《Android OTA 相關(guān)工具(一) 虛擬 A/B 之 snapshotctl》
- 《Android OTA 相關(guān)工具(二) 動態(tài)分區(qū)之 dmctl》
- 《Android OTA 相關(guān)工具(三) A/B 系統(tǒng)之 bootctl 工具》
- 《Android OTA 相關(guān)工具(四) 查看 payload 文件信息》
- 《Android OTA 相關(guān)工具(五) 使用 lpdump 查看動態(tài)分區(qū)》
- 《Android OTA 相關(guān)工具(六) 使用 lpmake 打包生成 super.img》
本文為洛奇看世界(guyongqiangx)原創(chuàng),轉(zhuǎn)載請注明出處。
文章鏈接:https://blog.csdn.net/guyongqiangx/article/details/132581720
1. lpmake 的編譯
lpmake 工具從 Android Q 版代碼開始引入,源碼位于 system/extras/partition_tools
目錄下,默認編譯 Android 后輸出到 out/host/linux-x86/bin/lpmake
,第一次編譯以后,通過 source 和 lunch 操作設(shè)置 Android 編譯環(huán)境后就可以引用。
例如:
$ source build/envsetup.sh
$ lunch aosp_panther-userdebug
$ which lpmake
/local/public/users/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake
$ lpmake -h
lpmake: option requires an argument -- 'h'
Must specify --device OR --device-size.
當然,也可以將 out/host/linux-x86/bin
添加到當前目錄下使用:
$ echo $PATH
/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ export PATH=${PWD}/out/host/linux-x86/bin:$PATH
$ echo $PATH
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin:/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ which lpmake
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake
$ lpmake -h
lpmake: option requires an argument -- 'h'
Must specify --device OR --device-size.
兩種方式都差不多,不過個人推薦前者。
2. lpmake 的幫助信息
關(guān)于一個工具,最好的文檔就是自己的幫助手冊,我這里順手將 lpmake 的 help 命令輸出貼在這里。
android-13.0.0_r41$ lpmake help
lpmake - command-line tool for creating Android Logical Partition images.Usage:lpmake [options]Required options:-d,--device-size=[SIZE|auto] Size of the block device for logical partitions.Can be set to auto to automatically calculate theminimum size, the sum of partition sizes plusmetadata-size times the number of partitions.-m,--metadata-size=SIZE Maximum size to reserve for partition metadata.-s,--metadata-slots=COUNT Number of slots to store metadata copies.-p,--partition=DATA Add a partition given the data, see below.-o,--output=FILE Output file.Optional:-b,--block-size=SIZE Physical block size, defaults to 4096.-a,--alignment=N Optimal partition alignment in bytes.-O,--alignment-offset=N Alignment offset in bytes to device parent.-S,--sparse Output a sparse image for fastboot.-i,--image=PARTITION=FILE If building a sparse image for fastboot, includethe given file (or sparse file) as initial data forthe named partition.-g,--group=GROUP:SIZE Define a named partition group with the givenmaximum size.-D,--device=DATA Add a block device that the super partitionspans over. If specified, then -d/--device-sizeand alignments must not be specified. The formatfor DATA is listed below.-n,--super-name=NAME Specify the name of the block device that willhouse the super partition.-x,--auto-slot-suffixing Mark the block device and partition names needingslot suffixes before being used.-F,--force-full-image Force a full image to be written even if nopartition images were specified. Normally, thiswould produce a minimal super_empty.img whichcannot be flashed; force-full-image will producea flashable image.--virtual-ab Add the VIRTUAL_AB_DEVICE flag to the metadataheader. Note that the resulting super.img willrequire a liblp capable of parsing a v1.2 header.Partition data format:<name>:<attributes>:<size>[:group]Attrs must be 'none' or 'readonly'.Device data format:<partition_name>:<size>[:<alignment>:<alignment_offset>]The partition name is the basename of the /dev/block/by-name/ path of theblock device. The size is the device size in bytes. The alignment andalignment offset parameters are the same as -a/--alignment and -O/--alignment-offset.
雖然上面的 help 信息包含了所有的選項說明,但我相信讀到這里的小伙伴只有少部分真正去閱讀了工具選項和說明。主要有幾點:
- 說明是英文的,一看英文就反感。沒說你,我自己就是這樣。
- 選項很枯燥,看了也不知道怎么用
- 喜歡手把手的那種詳細說明文檔
但我還是十分建議你花 5 分鐘去仔細閱讀一下工具所有選項以及相應(yīng)的說明,主要理由有以下幾點:
- 不喜歡看英文的文檔,那是因為你看得太少了,需要多看
- 選項很枯燥,看了也不知道怎么用,還是因為看得太少了
- 不要寄希望與別人的手把手文檔,有當然好,沒有就上幫助文檔,這才是必由之路。
說到底,自帶的幫助文檔是第一手的資料,閱讀第一手的資料,有助于你提高自己的學習能力。
3. lpmake 的用法
除了幫助文檔,看看 Android 里具體如何使用 lpmake 工具,對學習理解也有很大幫助。實在理解不了幫助文檔,那照著別人的用法依葫蘆畫瓢總比較容易一點。
3.1 示例 1
這里說說 Android 編譯中對 lpmake 的調(diào)用。
Android 編譯時,build_super_image.py
腳本會準備命令并調(diào)用 lpmake 生成 super.img,直接在 Android 編譯的 log 中搜索 lpmake 就可以看到詳細的命令。
這里以 Android 13 中編譯參考設(shè)備 panther 為例,看看 build_super_image.py
是如何調(diào)用 lpmake 的:
$ source build/envsetup.sh
$ lunch aosp_panther-userdebug
$ make dist -j80 2>&1 | tee make-dist.log
$ grep -ni lpmake make-dist.log
56:2023-08-30 02:26:10 - common.py - INFO : Running: "/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake --metadata-size 65536 --super-name super --metadata-slots 3 --virtual-ab --device super:8531214336 --group google_dynamic_partitions_a:8527020032 --group google_dynamic_partitions_b:8527020032 --partition system_a:readonly:886816768:google_dynamic_partitions_a --image system_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system.img --partition system_b:readonly:27312128:google_dynamic_partitions_b --image system_b=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_other.img --partition system_dlkm_a:readonly:348160:google_dynamic_partitions_a --image system_dlkm_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_dlkm.img --partition system_dlkm_b:readonly:0:google_dynamic_partitions_b --partition system_ext_a:readonly:301395968:google_dynamic_partitions_a --image system_ext_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_ext.img --partition system_ext_b:readonly:0:google_dynamic_partitions_b --partition product_a:readonly:368046080:google_dynamic_partitions_a --image product_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/product.img --partition product_b:readonly:0:google_dynamic_partitions_b --partition vendor_a:readonly:621752320:google_dynamic_partitions_a --image vendor_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/vendor.img --partition vendor_b:readonly:0:google_dynamic_partitions_b --partition vendor_dlkm_a:readonly:43040768:google_dynamic_partitions_a --image vendor_dlkm_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/vendor_dlkm.img --partition vendor_dlkm_b:readonly:0:google_dynamic_partitions_b --sparse --output out/target/product/panther/obj/PACKAGING/super.img_intermediates/super.img"
這里因為分區(qū)很多,所以 lpmake 的命令參數(shù)非常長,手動對這個 lpmake 命令整理一下會清楚很多:
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake \--metadata-size 65536 \--super-name super \--metadata-slots 3 \--virtual-ab \--device super:8531214336 \--group google_dynamic_partitions_a:8527020032 \--group google_dynamic_partitions_b:8527020032 \--partition system_a:readonly:886816768:google_dynamic_partitions_a \--image system_a=out/target/product/panther/system.img \--partition system_b:readonly:27312128:google_dynamic_partitions_b \--image system_b=out/target/product/panther/system_other.img \--partition system_dlkm_a:readonly:348160:google_dynamic_partitions_a \--image system_dlkm_a=out/target/product/panther/system_dlkm.img \--partition system_dlkm_b:readonly:0:google_dynamic_partitions_b \--partition system_ext_a:readonly:301395968:google_dynamic_partitions_a \--image system_ext_a=out/target/product/panther/system_ext.img \--partition system_ext_b:readonly:0:google_dynamic_partitions_b \--partition product_a:readonly:368046080:google_dynamic_partitions_a \--image product_a=out/target/product/panther/product.img \--partition product_b:readonly:0:google_dynamic_partitions_b \--partition vendor_a:readonly:621752320:google_dynamic_partitions_a \--image vendor_a=out/target/product/panther/vendor.img \--partition vendor_b:readonly:0:google_dynamic_partitions_b \--partition vendor_dlkm_a:readonly:43040768:google_dynamic_partitions_a \--image vendor_dlkm_a=out/target/product/panther/vendor_dlkm.img \--partition vendor_dlkm_b:readonly:0:google_dynamic_partitions_b \--sparse \--output out/target/product/panther/super.img
這里我把
--image
的路徑進行了簡化,將類似下面這樣的完整路徑:
out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system.img
使用另外一個比較簡短的路徑替代:
out/target/product/panther/system.img
上面這個 lpmake 命令的參數(shù)重點:
-
--metadata-size 65536
指定單個 metadata 數(shù)據(jù)的大小,通常為 64K,即 65536。
-
--super-name super
指定了 super 設(shè)備的設(shè)備名稱。
-
--metadata-slots 3
每一個 metadata 的 slot 數(shù)量,關(guān)于這個數(shù)值為什么是 3,而不是 2 在 《Android 動態(tài)分區(qū)詳解(一) 5 張圖讓你搞懂動態(tài)分區(qū)原理》有過疑惑,后面看情況是不是要單獨寫一點東西來說明分析這個。
-
--virtual-ab
用于設(shè)置 metadata 頭部的
VIRTUAL_AB_DEVICE
標識,解析這個標識需要 liblp 能夠解析 v1.2 版本的 metadata header 數(shù)據(jù)。 -
--device super:8531214336
指定 super 設(shè)備的大小,可以指定具體的大小數(shù)值,也可以通過
--device super:auto
自動計算所需的最小 size。 -
--group google_dynamic_partitions_a:8527020032
設(shè)備 super 內(nèi)的分組信息,使用
GROUP:SIZE
格式指定具體的 group 名稱,以及最大大小。 -
--partition system_a:readonly:886816768:google_dynamic_partitions_a
設(shè)備 super 內(nèi)的分區(qū)信息,使用
<name>:<attributes>:<size>[:group]
格式指定分區(qū)名稱,屬性,大小,以及所屬分組名稱。 -
--image system_a=out/target/product/panther/system.img
指定分區(qū)需要寫入的 image 路徑。
-
--sparse
指定生成的 super.img 是否是 sparse 格式,如果指定則輸出 sparse 格式的 super 鏡像。
-
--output out/target/product/panther/super.img
指定輸出的 super 鏡像文件路徑和文件名。
根據(jù)前面的提示,以下參數(shù)是必須的:
--device-size=[SIZE|auto]
--metadata-size=SIZE
--metadata-slots=COUNT
--partition=DATA
--output=FILE
主要就是用于生成 super 頭部的 metadata,缺少任何一個都會影響 metadata 數(shù)據(jù)的生成,所以是必須的。
上面的命令中,Android 參考設(shè)備 panther 上面的分區(qū)比較多,分區(qū)信息通過 --partition
指定,具體包含的鏡像通過 --image
指定。
至于 --group
以及 --image
參數(shù)都不是必須的。理論上你可以不用再 super 上創(chuàng)建分組,在制作 super 時也可以不用傳入具體分區(qū)的鏡像數(shù)據(jù),這樣生成的 super 就是一個只有 metadata 描述數(shù)據(jù),而沒有任何分區(qū)鏡像數(shù)據(jù)的空的 super.img,相當于 Android 編譯生成的 super_empty.img
3.2 示例 2
另外,文章《Android 動態(tài)分區(qū)詳解(二) 核心模塊和相關(guān)工具介紹》 中也介紹過 lpmake 工具的另外一個例子,可以參考上面的參數(shù)執(zhí)行分析這個命令:
lpmake --metadata-size 65536 --super-name super --metadata-slots 3 \--device super:3028287488 \--group bcm_ref_a:1509949440 --group bcm_ref_b:1509949440 \--partition system_a:readonly:1077702656:bcm_ref_a \--image system_a=out/target/product/inuvik/system.img \--partition system_b:readonly:0:bcm_ref_b \--partition vendor_a:readonly:104992768:bcm_ref_a \--image vendor_a=out/target/product/inuvik/vendor.img \--partition vendor_b:readonly:0:bcm_ref_b \--sparse --output out/target/product/inuvik/super.img
3.3 示例 3
這里再提供一個 Android 文檔中介紹 lpmake 時使用的例子:
lpmake --device-size 10240000000 \--metadata-size 65536 \--metadata-slots 2 \-o /tmp/super.img \-p "cache:2da85788-f0e1-4fda-9ee7-e5177eab184b:none:67108864" \-i "cache=out/target/hikey960/cache.img"
這個例子中,創(chuàng)建了一個 10GB 的 super 動態(tài)分區(qū),里面只包含了一個 64M 大小的 “cache” 分區(qū)。
現(xiàn)在,你可以手動自己使用 lpmake 來生成 super.img 了嗎?
4. 幾個思考題
到這里差不多應(yīng)該結(jié)束了,給大家留三個思考題:
問題1:system.img
和 system_other.img
仔細觀察上面第 3 節(jié)生成參考設(shè)備 panther 的 super.img 的命令中,system_a
分區(qū)和 system_b
分區(qū)傳入的鏡像文件竟然不一樣:
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake \--metadata-size 65536 \--super-name super \--metadata-slots 3 \--virtual-ab \--device super:8531214336 \--group google_dynamic_partitions_a:8527020032 \--group google_dynamic_partitions_b:8527020032 \--partition system_a:readonly:886816768:google_dynamic_partitions_a \--image system_a=out/target/product/panther/system.img \--partition system_b:readonly:27312128:google_dynamic_partitions_b \--image system_b=out/target/product/panther/system_other.img \...--sparse \--output out/target/product/panther/super.img
其中:
system_a
的 image 為:out/target/product/panther/system.img
system_b
的 image 為:out/target/product/panther/system_other.img
按照我的理解是 system_a
和 system_b
分區(qū),制作鏡像時可以提供一樣的文件,或者像其他分區(qū)一樣,system_b
不提供任何文件,僅保留一個空分區(qū)記錄。
但為什么這里會傳遞 system_other.img
給 system_b
分區(qū)呢?
鏡像文件 system_other.img
和 system.img
有什么區(qū)別?
問題 2:按照我上面的方法,研究下 super_empty.img
是如何生成的?
問題 3:為什么我 OTA 討論群里的這位群友反饋他生成的 super.img
只有幾十 K?
5. 其它
- 到目前為止,我寫過 Android OTA 升級相關(guān)的話題包括:
- 基礎(chǔ)入門:《Android A/B 系統(tǒng)》系列
- 核心模塊:《Android Update Engine 分析》 系列
- 動態(tài)分區(qū):《Android 動態(tài)分區(qū)》 系列
- 虛擬 A/B:《Android 虛擬 A/B 分區(qū)》系列
- 升級工具:《Android OTA 相關(guān)工具》系列
更多這些關(guān)于 Android OTA 升級相關(guān)文章的內(nèi)容,請參考《Android OTA 升級系列專欄文章導(dǎo)讀》。
如果您已經(jīng)訂閱了動態(tài)分區(qū)和虛擬分區(qū)付費專欄,請務(wù)必加我微信,備注訂閱賬號,拉您進“動態(tài)分區(qū) & 虛擬分區(qū)專欄 VIP 答疑群”。我會在方便的時候,回答大家關(guān)于 A/B 系統(tǒng)、動態(tài)分區(qū)、虛擬分區(qū)、各種 OTA 升級和簽名的問題,此群僅限專欄訂閱者參與~
除此之外,我有一個 Android OTA 升級討論群,里面現(xiàn)在有 400+ 朋友,主要討論手機,車機,電視,機頂盒,平板等各種設(shè)備的 OTA 升級話題,如果您從事 OTA 升級工作,歡迎加群一起交流,請在加我微信時注明“Android OTA 討論組”。此群僅限 Android OTA 開發(fā)者參與~
公眾號“洛奇看世界”后臺回復(fù)“wx”獲取個人微信。