第1章:开发环境搭建

AOSP源码下载与编译

做Camera HAL开发,第一步就是把AOSP环境搭起来。说实话,这一步看着简单,但坑不少。我刚开始带团队时,就有人因为环境没配好,白白浪费了两天时间。

先说说硬件要求。AOSP全量编译,说白了就是吃资源。我个人习惯用Ubuntu 20.04 LTS,内存至少16GB,硬盘留出300GB以上。为什么?因为一次完整编译下来,中间产物就能吃掉100多GB。你想想看,要是硬盘不够,编译到一半报错,那才叫崩溃。

下载源码,我推荐用清华或中科大的镜像站。速度比Google官方快太多了。具体操作:

# 安装repo工具
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

# 初始化仓库
mkdir aosp
cd aosp
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-13.0.0_r41

# 同步源码
repo sync -c -j8

这里有个细节:-j8是并行下载线程数,根据你的网络带宽和CPU核心数调整。我一般设成CPU核心数的两倍。

编译前,记得安装依赖库。Ubuntu 20.04上,我常用的命令:

sudo apt-get install git-core gnupg flex bison build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev \
lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig

嗯,这里要注意。不同Android版本依赖略有差异。比如Android 13开始,需要Python 3.8以上。我遇到过有人用Python 3.6编译,结果报了一堆语法错误。

编译命令很简单:

source build/envsetup.sh
lunch aosp_arm64-eng
make -j16

lunch时选哪个target?做Camera HAL开发,我建议选aosp_arm64-eng。eng版本带debug工具,方便调试。userdebug也行,但有些权限限制。

我的小技巧:第一次编译时,用make -j$(nproc)自动检测CPU核心数。但如果你在虚拟机里,建议手动设小一点,比如-j4。否则内存爆了,编译会直接卡死。

Camera HAL模块单独编译

全量编译一次太慢了,动辄一两个小时。实际开发中,我们只改Camera HAL的代码,没必要每次都全编。单独编译HAL模块,能省下大量时间。

Camera HAL的代码一般在hardware/interfaces/camerahardware/qcom/camera(高通平台)。我以AOSP原生HAL为例:

# 先source环境
source build/envsetup.sh
lunch aosp_arm64-eng

# 单独编译camera HAL模块
make android.hardware.camera.provider@2.4-impl -j8

# 或者编译整个camera相关模块
make camera -j8

编译完后,输出文件在out/target/product/xxx/vendor/lib/hw/下。比如camera.xxx.so。你可以用adb push直接推到设备上替换。

我曾经犯过一个错误:只编译了HAL模块,但忘了更新对应的manifest文件。结果刷进去后,Treble机制检测不到新模块,直接回退到旧版本。排查了半天才发现问题。

避坑指南:单独编译HAL模块时,一定要确认你的修改是否依赖其他模块的接口变更。如果改了HIDL接口,必须重新编译framework层。否则会出现接口不匹配,Camera服务直接crash。

刷机与调试环境配置

刷机这块,不同设备差异很大。我以Pixel设备为例,讲一下通用流程。

首先,解锁bootloader:

adb reboot bootloader
fastboot flashing unlock
# 按音量键确认解锁

解锁后,刷入我们编译好的镜像:

# 进入fastboot模式
adb reboot bootloader

# 刷入所有分区
fastboot flashall -w

# 或者只刷指定分区
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash vendor vendor.img

-w参数会清除用户数据。第一次刷机建议加上,避免旧数据干扰。后续迭代开发,可以不加-w,保留数据。

调试环境配置,我习惯用以下工具链:

工具 用途 安装方式
adb 设备通信、文件传输 AOSP自带
logcat 抓取日志 adb logcat
gdb Native调试 sudo apt install gdb-multiarch
strace 系统调用跟踪 adb shell strace
perf 性能分析 adb shell perf

抓取Camera HAL日志,我常用的命令:

# 过滤Camera相关日志
adb logcat -s CameraService:V CameraHal:V

# 保存到文件
adb logcat -s CameraService:V CameraHal:V > camera_log.txt

# 实时查看并过滤关键字
adb logcat | grep -E "Camera|HAL|error"

调试Native代码时,我推荐用gdb配合gdbserver。具体步骤:

# 在设备上启动gdbserver
adb shell gdbserver :5039 --attach [pid]

# 在主机上连接
adb forward tcp:5039 tcp:5039
gdb-multiarch out/target/product/xxx/symbols/vendor/lib/hw/camera.xxx.so
(gdb) target remote :5039
核心要点:调试环境配置的关键是符号表。编译时一定要保留debug信息。在Android.mkAndroid.bp中,确保LOCAL_STRIP_MODULE := false。否则你看到的堆栈全是地址,根本没法定位问题。

最后,说一个我踩过的坑。有一次刷机后,Camera HAL一直加载失败。查了半天,发现是SELinux策略没更新。新编译的HAL模块需要对应的te文件权限。解决方案:要么关闭SELinux(adb shell setenforce 0),要么更新sepolicy并重新编译boot.img。

嗯,环境搭建就这些。看似繁琐,但一次配好,后面开发就顺畅了。下一章,我们开始讲Camera HAL的架构和初始化流程。