⚠️ 注意:本人非专业 Android 开发者,本文仅供参考,如有错误,欢迎指正!
本文章以适配OPPO Reno5 Pro+ 为例, OPPO Reno5 Pro+ 为 A only 设备, 支持动态分区 , 不兼容 GKI, VNDK 版本 30。
编译服务器系统: Ubuntu 20.04.4 lts
需要准备的东西
- 可以编译 Android 的高性能 PC 或服务器(需提前预留32gb的ram和100g的设备存储空间)
- 国际互联网连接
- 一台root过的OPPO Reno5 Pro+
准备开始
安装编译依赖
1 | sudo apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev libelf-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev git |
配置 repo
1 | sudo curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo |
同步 TWRP 源码
1 | mkdir twrp && cd twrp |
如果安卓版本为安卓10及其以上,请更换网址为:
1 | repo init -u https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp -b twrp-12.1 --depth=1 |
注:如果同时安转了python2.7和python3,运行repo时可能会出现以下状况:
1 | File "/usr/bin/repo", line 51 |
解决方法:
1 | /usr/bin/python3 /usr/bin/repo sync |
或修改 /usr/bin/repo
1 | #!/bin/python |
改成
1 |
源码同步成功后会占用磁盘20g-30g的空间。
初始化编译必要文件
⚠️ 注意:下列步骤将由xxxx替代要适配的手机代号,yyyy代替手机厂商。
不管是编译 Android 还是 TWRP,这些文件都是必要的:
- Android.mk
- AndroidProduct.mk
- BoardConfig.mk
- twrp_xxxx.mk
这几个文件可以直接从其他的twrp设备树拿,然后进行修改。
Android.mk、AndroidProduct.mk、twrp_xxxx.mk 一般情况下无需进行修改
编译 TWRP 需要对 BoardConfig.mk 等文件进行修改
修改 BoardConfig.mk
1 | DEVICE_PATH := device/yyyy/xxxx |
此处定义了设备树的位置。
1 | ALLOW_MISSING_DEPENDENCIES := true |
由于同步的只有 TWRP 源码,编译时需要打开这个。
1 | BUILD_BROKEN_DUP_RULES := true |
这两个选项可能会解决一些编译错误。当有两个或更多的条目试图将文件复制到相同的目标位置时。这个标志的作用是允许覆盖先前定义的目标命令,而不是报错。
1 | # Architecture |
这里定义要适配的机型的cpu的一些信息。
1 | TARGET_BOARD_SUFFIX := _64 |
如果适配的安卓设备的soc是64位soc,且系统也是64位,请启用它。
1 | TARGET_OTA_ASSERT_DEVICE := xxxx |
此处定义了设备ota时候的机型代号,ota机型检查的时候会检查是否匹配。
1 | # Bootloader |
此处定义了bootloader的一些信息。
1 | BOARD_USES_MTK_HARDWARE := true |
这两个选项仅适用于mtk芯片组。
1 | # Platform |
此处定义了cpu的代号。
1 | # BOARD_BOOTIMG_HEADER_VERSION := 2 |
使用源码编译才使用此部分。
1 | BOARD_KERNEL_CMDLINE := ttyMSM0,115200n8 earlycon=msm_geni_serial,0xa90000 androidboot.hardware=qcom androidboot.console=ttyMSM0 androidboot.memcg=1 lpm_levels.sleep_disabled=1 video=vfb:640x400,bpp=32,memsize=3072000 msm_rtb.filter=0x237 service_locator.enable=1 androidboot.usbcontroller=a600000.dwc3 swiotlb=2048 loop.max_part=7 cgroup.memory=nokmem,nosocket reboot=panic_warm kpti=off buildvariant=user |
使用预编译内核。你需要提取手机的boot.img并使用Android Image Kitchen来获取预编译内核,dtb和dtbo(如果有)以及cmdline。
然后替换cmdline。
再将预编译内核放入引用的路径。这里引用的路径是$(DEVICE_PATH)/prebuilt/
1 | # Android Verified Boot |
此处定义了avb的一些信息。
1 | # Metadata |
在twrp中使用metadata分区。
1 | # Hack: prevent anti rollback |
加入补丁更新日期来回避防回滚机制。
1 | # Partitions |
此处定义了boot分区和recovery分区的大小,以及块大小。修改分区大小时要注意单位是b而不是kb。
1 | # Dynamic Partition |
此处定义了动态分区的信息。可按需修改。
1 | # File systems |
此处依次定义了system,vendor和data分区的文件系统,以及vendor分区的相对路径。
1 | # Fstab |
此处定义了fstab的位置。可提取recovery中的ramdisk.cpio中的进行使用。
1 | # TWRP Configuration |
此处依次定义了twrp要使用的主题,亮度调节的内核节点,亮度调节,添加亚洲语言, 是否在 wipe data 时忽略 misc,是否添加加密,解密所需依赖源码路径等信息。
注:亮度调节的内核节点语言根据本机的位置进行修改。
1 | TW_USE_TOOLBOX := true |
此处定义了twrp是否启用调试功能,例如toolbox,logcat等。
1 | # Include some binaries |
此处定义twrp编译时引用的第三方库。
1 | TARGET_USES_MKE2FS := true |
此处添加了mke2fs,可将分区格式化成f2fs。
1 | TW_DEFAULT_LANGUAGE := zh_CN |
此处设置了启动twrp时的默认语言为中文。
1 | TW_OZIP_DECRYPT_KEY := 0000 |
此处定义了刷入ozip时解密ozip的秘钥。
1 | AB_OTA_UPDATER := true |
如果是 A/B 分区的话还得加入这些。
修改 device.mk
1 | LOCAL_PATH := device/yyyy/xxxx |
定义local_path变量,一般有这一行就够了。
1 | PRODUCT_USE_DYNAMIC_PARTITIONS := true |
是否启用动态分区。如果设备是动态分区就启用。
1 | # Crypto |
此处添加解密所需依赖。
1 | # Soong namespaces |
此处定义Soong namespaces的路径。
注:下述内容需要设备为A/B分区。
1 | AB_OTA_UPDATER := true |
此处定义了是否启用A/B支持。
1 | AB_OTA_PARTITIONS += \ |
此处定义了使用 A/B 特性的分
1 | AB_OTA_POSTINSTALL_CONFIG += \ |
此处定义了A/B分区ota的一些选项。
1 | PRODUCT_PACKAGES += \ |
此处定义了需要引用的包。
修改完成后,在 twrp_xxxx.mk 里调用
1 | $(call inherit-product, device/yyyy/xxxx/device.mk) |
配置 TWRP 分区表
可以从本机recovery里提取一份recovery.fstab并放在之前引用的位置。我这里引用的是recovery/root/system/etc/recovery fastb
然后新建文件twrp.flags并放在与recovery.fastb相同的路径
。
twrp.flags文件示例:
1 | # mount point fstype device device2 flags |
关于 flags:
- 如果是 A/B 设备,请给使用 A/B 特性的分区定义
slotselect
- 用 backup 来定义可备份分区
- display 用来自定义分区名
- encryptable 来定义加密类型
- removable 用来定义可否热拔插
如果是A/B分区,还需要添加recovery.wipe
:
1 | # All the partitions to be wiped (in order) under recovery. |
init.rc
不同机型,init 部分也不一样
可以复制recovery.img里面的
bootctrl 和 gpt-utils
如果你的设备采用 A/B 分区,那必须编译这两个组件
确保 tree 里面有编译 bootctrl 和 gpt-utils
这两个东西可以从其它机型的 tree 里面拿,通用的
开始编译
上面的东西都配置好后就可以开始编译了
1 | cd twrp |
如果设备不是 A/B 分区
1 | mka recoveryimage |
制作卡刷包
需要再BoardConfig.mk加入
1 | USE_RECOVERY_INSTALLER := true |
新建以下目录:
1 | installer |
添加magiskboot到installer目录
添加update-binary到installer/META-INF/com/google/android/目录:
1 | #!/sbin/sh |
注:A/B分区可能需要准备installer/META-INF/MANIFEST.MF,installer/META-INF/CERT.SF,installer/META-INF/CERT.RSA
-------------本文结束感谢您的阅读-------------