实战项目:从零构建一个定制 ROM
说实话,这个章节是我整个课程里最期待的部分。前面讲了那么多理论、源码、编译流程,现在终于到了动真格的时候。从零构建一个定制 ROM,听起来很唬人,其实拆开来看就是四件事:功能裁剪、UI 定制、性能优化、OTA 发布。我当年第一次做这个项目时,踩的坑比代码行数还多,今天我把这些经验都摊开来跟你聊聊。
一、项目整体架构
先给你看一张图,这是我个人习惯用的项目流程。你照着这个走,基本不会迷路。
这个流程我反复调整过很多次。一开始我总想着一步到位,结果每次编译到一半就崩。后来学乖了,按这个顺序走,每一步都验证通过再往下。
二、功能裁剪:做减法比做加法难
功能裁剪,说白了就是删东西。但删什么、怎么删,这里头门道很多。
2.1 确定裁剪目标
我建议你先想清楚:这个 ROM 给谁用?用在什么设备上?
- 低端设备:砍掉动态壁纸、Google 服务、3D 特效、多余输入法
- 行业专用设备:只保留核心应用,比如 POS 机、扫码器驱动
- 极客定制:保留 AOSP 基础,去掉厂商预装应用
2.2 具体操作
在 AOSP 源码中,裁剪主要通过修改 device/<厂商>/<设备名>/device.mk 文件实现。
# 示例:裁剪 device.mk
# 删除不需要的模块
PRODUCT_PACKAGES := \
Launcher3 \
Settings \
SystemUI \
# 以下为删除项(注释掉或移除)
# LiveWallpapers \
# LiveWallpapersPicker \
# Email \
# Calendar \
# Exchange2 \
# PrintSpooler \
# WallpaperPicker \
# BasicDreams \
# PhotoTable \
# Galaxy4 \
# HoloSpiralWallpaper \
# NoiseField \
# PhaseBeam
# 禁用不必要的服务
PRODUCT_PROPERTY_OVERRIDES += \
ro.config.low_ram=true \
ro.sys.fw.bg_apps_limit=16
嗯,这里要注意:有些模块之间有依赖关系。比如你删了 WallpaperPicker,但 Launcher3 里还引用了它,那编译就会报错。我的做法是:先 grep 一下这个模块被谁引用了。
# 查找模块依赖
grep -r "WallpaperPicker" vendor/ device/ packages/
三、UI 定制:让 ROM 看起来像你的作品
UI 定制是最有成就感的部分。你想想看,开机第一眼看到的是你自己的设计,那感觉完全不一样。
3.1 修改开机动画
开机动画在 frameworks/base/core/res/assets/images/ 目录下。其实它是一个 ZIP 包,里面包含一系列 PNG 图片和一个 desc.txt 描述文件。
# desc.txt 示例
480 800 15
p 1 0 part0
p 0 0 part1
# 说明:
# 第一行:宽 高 帧率
# p 1 0 part0:播放一次,不循环
# p 0 0 part1:循环播放
3.2 修改系统主题
系统主题主要涉及 frameworks/base/core/res/res/ 下的 values 文件。比如修改主色调:
<!-- frameworks/base/core/res/res/values/colors.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 修改为主色调为深蓝色 -->
<color name="primary_color">#FF1565C0</color>
<color name="primary_dark_color">#FF0D47A1</color>
<color name="accent_color">#FF00BCD4</color>
<!-- 状态栏颜色 -->
<color name="status_bar_color">#FF0D47A1</color>
</resources>
改完之后,记得重新编译 framework-res.apk:
make framework-res -j8
3.3 替换默认启动器
我个人习惯用 Lawnchair 作为基础,因为它开源且可定制性强。把第三方启动器源码放到 packages/apps/ 目录下,然后在 device.mk 里添加:
PRODUCT_PACKAGES += \
Lawnchair \
# 移除原生的 Launcher3
# Launcher3
四、性能优化:让 ROM 飞起来
性能优化这块,我踩过的坑最多。说白了,优化就是找瓶颈。CPU、内存、IO、GPU,哪个是短板就优化哪个。
4.1 内核优化
内核参数调整是最直接的手段。修改 device/<厂商>/<设备名>/init.rc 或 init.<设备名>.rc:
# 调整 CPU 调度器
on boot
write /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor "interactive"
write /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor "interactive"
# 调整 I/O 调度器
write /sys/block/mmcblk0/queue/scheduler "cfq"
# 降低 swappiness 减少内存交换
write /proc/sys/vm/swappiness 10
# 启用 zram
write /sys/block/zram0/disksize 256M
swapon /dev/block/zram0
4.2 内存优化
低内存设备(1GB 以下)必须做内存优化。我常用的手段:
- 启用
ro.config.low_ram=true,系统会自动减少后台进程 - 调整 LMK(Low Memory Killer)阈值
- 禁用动画缩放:
ro.min.fling_velocity=4000
# 在 build.prop 中添加
ro.sys.fw.bg_apps_limit=12
ro.config.low_ram=true
persist.sys.force_highendgfx=false
4.3 应用预优化
这个技巧知道的人不多。在编译时对系统应用做 dex2oat 预编译,可以显著提升首次启动速度。
# device.mk 中启用
WITH_DEXPREOPT := true
DONT_DEXPREOPT_PREBUILTS := false
不过要注意,预编译会增加系统分区大小。我算过,大概每个应用多占 5-10MB。
五、OTA 发布:让用户能升级
OTA 是定制 ROM 的最后一公里。没有 OTA,你的 ROM 就是个一次性产品。
5.1 生成 OTA 包
AOSP 自带的工具在 build/tools/releasetools/ 目录下。基本流程:
# 1. 编译完整 ROM
source build/envsetup.sh
lunch aosp_<设备名>-userdebug
make -j8
# 2. 生成 OTA 包(增量更新)
./build/tools/releasetools/ota_from_target_files \
-i previous_target_files.zip \
-n \
-v \
-p out/host/linux-x86 \
-k build/target/product/security/testkey \
out/target/product/<设备名>/obj/PACKAGING/target_files_intermediates/<设备名>-target_files-*.zip \
update.zip
-i 参数指定上一个版本,结果生成了全量包,用户每次都要下载 1GB 多的文件。后来改成增量包,每次只有 50-100MB,体验好太多了。
5.2 OTA 服务器搭建
最简单的方案是用 Nginx 做静态文件服务器:
# nginx 配置
server {
listen 80;
server_name ota.example.com;
root /var/www/ota;
location / {
autoindex on;
}
# 限制 OTA 包下载速度,避免占满带宽
location /updates/ {
limit_rate 5m;
}
}
然后在 ROM 中内置 OTA 应用,指向你的服务器地址。我推荐用 OpenDelta 或自己写一个简单的 OTA 检查器。
5.3 版本管理
建议用语义化版本号:主版本.次版本.修订号。比如 v1.2.3。每次发布时在 build.prop 中更新:
ro.build.version.release=12
ro.build.version.incremental=v1.2.3
ro.build.display.id=MyROM-v1.2.3
六、测试验证:别急着发布
我吃过这个亏。有一次编译完觉得没问题,直接发布了,结果用户反馈 WiFi 连不上。排查后发现是裁剪时删了一个 WiFi 相关的 HAL 库。
建议的测试清单:
| 测试项 | 测试方法 | 预期结果 |
|---|---|---|
| 开机启动 | 冷启动 3 次 | 每次 < 30 秒 |
| WiFi/蓝牙 | 连接/断开 10 次 | 无异常断开 |
| 电话/短信 | 拨打/接收测试 | 声音清晰 |
| 相机 | 拍照/录像 5 分钟 | 无闪退 |
| OTA 升级 | 从 v1.0 升到 v1.1 | 数据不丢失 |
嗯,差不多就这些了。从零构建一个定制 ROM,说难不难,说简单也不简单。关键是每一步都要稳,别想着一步到位。我当年第一个 ROM 做了整整两个月,现在回想起来,那些坑都是财富。
如果你在做的过程中遇到问题,欢迎来找我交流。记住:编译失败是常态,别灰心,查日志、问社区、看源码,总能解决的。
公众号:蓝海资料掘金营,微信deep3321