第二章 开发环境搭建:AOSP 源码下载、编译环境配置(Ubuntu)、模拟器与真机调试、必备工具链
好,咱们正式开始动手了。这一章我带你把开发环境搭起来。说实话,Camera HAL 开发最怕什么?最怕环境没配好,编译跑不通,最后发现是 JDK 版本不对。我当年刚接触 AOSP 时,光配环境就折腾了两天。嗯,咱们别走弯路,一次搞定。
2.1 AOSP 源码下载:别让网络卡住你
下载 AOSP 源码,说白了就是跟 Google 的服务器打交道。国内开发者最头疼的就是网络问题。我个人习惯用清华或中科大的镜像站,速度稳定很多。
先装 repo 工具:
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
然后初始化仓库。这里我建议你选一个稳定的分支,比如 android-13.0.0_r41。为什么?因为太新的分支可能有坑,太老的又缺特性。
mkdir aosp_camera
cd aosp_camera
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-13.0.0_r41
repo sync -j4 -c
同步完成后,你会看到整个 Android 源码树。Camera HAL 相关的代码主要在 hardware/interfaces/camera/ 和 hardware/libhardware/modules/camera/ 下。你想想看,几百个 GB 的代码,其实我们真正关心的就这几个目录。
2.2 编译环境配置:Ubuntu 下的准备工作
Ubuntu 20.04 是我最推荐的版本。为什么?因为 22.04 的 Python 版本太高,AOSP 有些脚本还不兼容。我踩过这个坑,编译到一半报错,查了半天才发现是 Python 3.10 的问题。
安装必要依赖:
sudo apt-get update
sudo apt-get install -y 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
JDK 安装是个坑。AOSP 13 需要 OpenJDK 11,但 Ubuntu 默认源里的是 OpenJDK 17。我建议手动安装:
sudo apt-get install openjdk-11-jdk
java -version # 确认版本是 11.x
export USE_CCACHE=1 和 export CCACHE_DIR=/path/to/ccache 加到 ~/.bashrc 里。ccache 能大幅加速二次编译,尤其是你只改了一两个文件时。
设置文件描述符限制也很重要。AOSP 编译时会打开大量文件,默认的 1024 不够用:
echo "ulimit -n 4096" >> ~/.bashrc
source ~/.bashrc
2.3 编译 AOSP:第一次跑起来
环境配好了,咱们开始编译。先加载环境变量:
source build/envsetup.sh
lunch aosp_x86_64-eng
这里我解释一下。lunch 后面的 target 选择 aosp_x86_64-eng 是为了在模拟器上跑。如果你要编译真机版本,比如 Pixel 6,那就选 aosp_bluejay-eng。eng 版本带 debug 符号,方便我们调试。
然后开始编译:
make -j$(nproc) 2>&1 | tee build.log
第一次编译大概需要 2-3 小时,取决于你的机器配置。我建议用 tee 把日志保存下来,万一出错方便排查。我记得有一次编译到 90% 报错了,一看日志是某个模块的依赖没装全,省了我不少时间。
核心要点: 如果你只修改了 Camera HAL 相关代码,不需要全量编译。用 mma 命令可以只编译当前模块,速度飞快。比如在 hardware/interfaces/camera/ 目录下执行 mma,几分钟就搞定了。
2.4 模拟器与真机调试
编译完成后,启动模拟器:
emulator -show-kernel -memory 2048 -cores 4
模拟器调试 Camera HAL 有个局限——它用的是虚拟摄像头,跟真机行为有差异。我建议你尽早切换到真机。真机调试需要先解锁 bootloader,然后刷入编译好的镜像:
adb reboot bootloader
fastboot flashall -w
fastboot reboot
这里有个坑:fastboot flashall 会清空用户数据。所以刷机前记得备份。我曾经手滑没加 -w 参数,结果数据还在,但系统分区出了问题,折腾了半天才恢复。
真机调试时,我常用的命令:
adb logcat -s CameraHal:V # 只看 Camera HAL 日志
adb shell dumpsys media.camera # 查看摄像头状态
adb shell ls -l /dev/video* # 检查摄像头设备节点
2.5 必备工具链:adb, lldb, gdb
工具链是咱们的武器。adb 不用多说,但有几个高级用法你可能不知道:
| 命令 | 用途 | 我踩过的坑 |
|---|---|---|
adb root |
获取 root 权限 | 有些 eng 版本默认没 root,需要重新编译 |
adb remount |
重新挂载系统分区为可写 | 如果没 root,remount 会失败 |
adb push/pull |
传输文件 | 注意权限问题,有时需要 chmod |
adb shell setprop |
动态修改系统属性 | 可以用来开关 HAL 的 debug 日志 |
lldb 和 gdb 用于 native 层调试。Camera HAL 是 C++ 写的,崩溃时用 gdb 看 backtrace 最直接:
adb shell gdbserver :5039 /system/bin/cameraserver
# 在主机端
adb forward tcp:5039 tcp:5039
gdbclient :5039
ALOGD 日志,配合 adb logcat -s CameraHal:V 实时查看。比 gdb 轻量很多,适合快速定位问题。但遇到段错误(segfault)时,还是得上 gdb。
另外,别忘了 addr2line 这个工具。当你在 logcat 里看到类似 pc 0x1234 的地址时,用它转换成源码行号:
addr2line -e out/target/product/xxx/symbols/system/lib64/hw/camera.xxx.so 0x1234
嗯,这一章内容不少。你先把环境搭好,编译跑通,后面咱们才能真正开始写 Camera HAL 代码。记住,环境搭建是基础,基础不牢,地动山摇。我当年就是吃了这个亏,后来每次换机器都老老实实按这个流程走一遍。