在Android源码调试过程中,需要通过系统化的方法定位和解决问题。以下是详细步骤和关键技术要点:
一、环境准备
1. 源码同步与编译
- 使用`repo`工具同步AOSP源码,确保分支与目标设备系统版本一致。编译时通过`lunch`选择正确的产品配置(如`aosp_arm64-eng`),`eng`版本会默认开启调试符号。
- 推荐使用Linux环境(Ubuntu 20.04+),SSD存储可显著提升编译速度。编译命令:
source build/envsetup.sh
lunch aosp_arm64-eng
m -j$(nproc)
2. 调试工具链配置
- 安装GDB(建议使用AOSP预编译的`gdbclient.py`)或LLDB。对于Native层调试,需配置目标设备的`gdbserver`端口转发:
adb forward tcp:5039 tcp:5039
二、Java层调试
1. Android Studio关联源码
- 通过`IDE`导入`frameworks/base`等核心模块,在`Project Structure`中指定源码路径为AOSP根目录。若使用模块化开发,需同步`android.ipr`文件。
- 调试系统进程需`adb root`权限,通过`Attach Debugger`选择目标进程(如`system_process`)。
2. 日志增强
- 在待调试的Java类中添加详细日志:
java
import android.util.Log;
Log.d("TAG", "Variable value: " + variable);
- 通过`logcat`过滤日志:
adb logcat -v threadtime -s TAG:D *:S
三、Native层深度调试
1. 符号文件加载
- 使用`addr2line`解析崩溃堆栈:
aarch64-linux-android-addr2line -e symbolso/file.elf 0x1234
- 对于动态库,需确保设备端的`/system/lib64/`与本地符号文件一致。
2. GDB高级技巧
- 在`gdbinit`中预加载断点命令:
break android::Bitmap::allocateHeapBitmap
commands
print width
print height
continue
end
- 使用`catch syscall`监控特定系统调用事件。
四、内核调试
1. Kernel模块
- 编译内核时启用`KGDB`和动态打印:
CONFIG_KGDB=y
CONFIG_DEBUG_FS=y
- 通过`sysrq`触发调试中断:
echo g > /proc/sysrq-trigger
2. FTrace实时分析
- 监控调度事件:
echo 1 > /sys/kernel/debug/tracing/events/sched/enable
cat /sys/kernel/debug/tracing/trace_pipe
五、性能分析工具
1. Systrace整合
- 采集系统级数据:
python systrace.py -o trace.html -t 10 sched freq idle
- 结合`CustomEvent`在代码中插入标记:
java
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performMeasure");
2. Perfetto深度分析
- 录制完整系统轨迹:
adb shell perfetto --txt -c /data/misc/perfetto-config.pbtxt -o /data/misc/trace.perfetto-trace
- 分析CPU调度瓶颈时可关注`linux.ftrace`数据源。
六、疑难问题处理
1. 堆栈混淆还原
- ProGuard混淆后的堆栈需通过`mapping.txt`还原:
retrace.sh -verbose mapping.txt crash.log
- 对于ART虚拟机,可使用`dexdump`分析ODEX文件结构。
2. 内存问题诊断
- 启用`libc`的Malloc调试:
adb shell setprop libc.debug.malloc.options backtrace
adb shell setprop libc.debug.malloc.program app_process
- 通过`AddressSanitizer`检测内存错误:
LOCAL_SANITIZE := address
七、自动化测试集成
1. CTS/VTS用例调试
- 单独运行测试模块:
atest FrameworksTelephonyTests
- 提取JUnit测试报告:
adb pull /sdcard/test_result.xml
2. Monkey压力测试
- 注入特定事件序列:
adb shell monkey -p com.android.phone -v --throttle 100 500
扩展知识
ART调试接口:通过`jdwp`协议可连接`libart.so`的JDWP实现,使用`openjdkjvmti`进行字节码插桩。
Binder事务:在`ServiceManager`调试时,开启Binder内核日志:
echo 1 > /sys/module/binder/parameters/debug_mask
HAL层调试:对于HIDL服务,可通过`lshal debug`命令获取接口实例状态。