本指南概述了用于调试在 SDV 平台上运行的服务和应用的基本工具和技术。
连接到设备
用于连接设备并与之互动的主要工具是 Android 调试桥 (adb)。验证 adb 是否在系统的路径中。
使用网络连接
如果设备位于同一网络中,并且您知道其 IP 地址,则可以通过以太网进行连接。我们的系统专门使用网络连接进行 adb:
# Connect to the device using its IP address and default port
adb connect <device_ip_address>:5555
连接到多部设备
如需通过单个工作站管理多部设备,您可以通过不同的 IP 地址连接到这些设备。如果您在单个主机上运行多个虚拟机,则需要为每部设备分配不同的端口。为此,您需要配置每个 SDV 设备上的 adb 守护程序,使其监听唯一端口,例如,第一个设备监听 5555 端口,第二个设备监听 5556 端口。您还可以配置主机,以将这些端口转发到不同的 guest:
# Connect to the first device
adb connect <device_1_ip_address>:5555
# Connect to a second device
adb connect <device_2_ip_address>:5555
# Connect to a second VM on first device on different port
adb connect <device_1_ip_address>:5556
# List all connected devices to verify
adb devices
在运行后续 adb 命令时,您可以使用 -s 标志及其完整地址 (ip:port) 来定位特定设备:
# Run a shell command on the second VM on first device in the above example
adb -s <device_1_ip_address>:5556 shell
查看日志
当服务出现故障或行为异常时,请先检查日志。
使用 logcat(Android 日志)
logcat 显示来自系统服务、代理和服务捆绑包的日志:
# View all logs in real-time
adb logcat
# Filter logs by a specific tag (e.g., the name of your service)
adb logcat -s MyServiceTag
# Filter logs by priority (V: Verbose, D: Debug, I: Info, W: Warn, E: Error, F: Fatal)
# This shows only Error and Fatal messages for a specific tag
adb logcat MyServiceTag:E *:S
# Clear old logs before viewing new ones
adb logcat -c && adb logcat
# Show all logs and return
adb logcat -d
# Color logs by level
adb logcat -v color
# Show timestamps as time since boot
adb logcat -v monotonic
使用 dmesg(内核日志)
dmesg 显示来自 Linux 内核的日志。这对于调试以下内容至关重要:
- 硬件和驱动程序问题
- 内核崩溃
- SELinux 拒绝 (
avc: denied) - 也会显示在 logcat 中
# View all kernel messages
adb shell dmesg
# Follow kernel messages in real-time
adb shell dmesg -w
访问 Cuttlefish 上的日志
在 Cuttlefish 虚拟设备上运行时,您可以直接从宿主机的文件系统中访问日志文件。如果 adb 不可用,这会特别有用。启动 Cuttlefish 时,它会输出所有调试路径,您还可以使用 cvd fleet 查找所有正在运行的实例。
- Logcat(Android 日志):
cuttlefish/instances/cvd-1/logs/logcat - 内核日志:
cuttlefish/instances/cvd-1/logs/kernel.log - Cuttlefish 启动器日志:
cuttlefish/instances/cvd-1/logs/launcher.log(有助于调试 Cuttlefish 环境本身)
您可以使用 cat、less 或 tail -f 等标准命令行工具实时查看这些文件。
与 shell 和文件系统互动
获取 shell 访问权限,以便直接在设备上运行命令、检查进程状态和浏览文件系统:
# Open an interactive shell on the device
adb shell
# From within the shell, you can check running processes
ps -A
# Or check the status of a specific service managed by init
getprop init.svc.<service_name>
执行文件系统操作
使用 adb push 和 adb pull 在宿主机和设备之间移动文件。您可以使用此功能来部署测试脚本、更新配置或检索崩溃转储:
# Push a file from your computer to the device
adb push my_local_file.txt /data/local/tmp/
# Pull a file from the device to your computer
adb pull /data/tombstones/tombstone_00 .
调试应用 (C++/Rust)
您可以联机或离线调试应用。
使用 lldb 进行实时调试
lldb 是 Android Studio 中的默认调试器,通常是现代 C++ 和 Rust 开发的首选。
请按照以下设置步骤操作:
重启 adb 以允许 root 权限(转发所需)。使用此权限设置端口转发。在主机上,运行:
adb root如果二进制文件具有调试符号,请推送未剥离的版本。您可以在
out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE]中找到未剥离的版本。例如,如需从system_ext和sdv_core_cf上传rpcagent,请运行:adb push out/target/product/sdv_core_cf/symbols/system_ext/bin/rpcagent /data/local/tmp现在,未剥离的版本位于
/data/local/tmp中。使用
lldbclient.py便利脚本连接到 LLDB 客户端:# Run and connect a binary on device, run on host: lldbclient.py -r /data/local/tmp/rpcagent # Connect to an existing process with PID 2759 lldbclient.py -p 2759此脚本可远程连接 lldb。如需查看所有可用标志,请运行
lldbclient.py。请参阅 IDE 文档,了解如何将其连接到 lldb。
分析崩溃转储 (Tombstone)
当服务崩溃时,系统会在 /data/tombstones/ 中生成一个 tombstone 文件。该文件包含堆栈轨迹、内存映射和其他关键信息。
提取 tombstone 文件,然后使用可识别符号的工具(例如 lldb 或专用脚本)通过未剥离的二进制版本对其进行分析。
分析性能
SDV 支持多种用于衡量性能的工具。
检查 CPU 和内存用量
top:提供按 CPU 使用情况排序的正在运行的进程的实时视图。adb shell top -m 10 # Show top 10 processesprocrank:详细列出特定进程或整个系统的内存用量。adb shell procrank
使用 dumpsys 获取服务状态
dumpsys 是一种强大的工具,可用于查询任何 Android 系统服务的内部状态。
# List all available services
adb shell dumpsys -l
# Dump the state of a specific service or agent
adb shell dumpsys <service_name>
使用 torq 进行性能分析
torq 是一款命令行工具,可简化 Android 上的分析和跟踪任务。它允许在系统性能分析期间运行 Simpleperf、Perfetto 和其他典型任务。
使用 Perfetto 进行跟踪
Perfetto 是 Android 上用于进行系统级跟踪的标准工具。借助 Perfetto,您可以记录系统事件、应用级跟踪点和性能计数器,并在时间轴上直观呈现这些数据。
主要步骤:
- 在 C++ 或 Rust 代码中添加轨迹点:
- C++:将 Perfetto SDK 与
TRACE_EVENT宏搭配使用。 - Rust:使用
tracingcrate,该 crate 会发出与 Perfetto 兼容的 ATrace 事件。
- C++:将 Perfetto SDK 与
- 创建一个 textproto 配置文件,以指定数据源(例如
ftrace、track_event)、类别和标记。 - 使用
record_android_trace脚本 (external/perfetto/tools/record_android_trace) 和配置文件来捕获设备的轨迹。 - 在 Perfetto Web 界面中打开生成的跟踪文件,以分析系统行为、识别瓶颈并了解服务互动。
如需了解有关插桩、配置和收集的详细说明,请参阅使用跟踪深入了解系统性能。
使用 Simpleperf 进行性能剖析
Simpleperf 是一款通用的命令行工具,用于在 Android 上进行性能分析,类似于 Linux perf。
常见使用场景:
- CPU 性能剖析:识别消耗最多 CPU 时间的函数。
- Off-CPU 分析:分析线程为何处于休眠或阻塞状态。
- 硬件计数器:访问硬件性能计数器。
示例命令:
# Go to simpleperf scripts
cd system/extras/simpleperf/scripts
# Profile system for 20 seconds and record call graph
./app_profiler.py --system_wide -r "--call-graph fp --duration 20"
# Record a profile for a specific process (PID 1)
./app_profiler.py --pid 1 -r "--call-graph fp --duration 5"
# Pull the profile data
adb pull /data/local/tmp/perf.data .
# Generate a report with symbol resolution
./report_html.py --add_source_code --source_dirs $ANDROID_BUILD_TOP --add_disassembly -o report.html
Simpleperf 还提供了更多事件和选项。如需查看全面的文档,请参阅 Simpleperf 指南。
SELinux 拒绝
症状:您的服务无法启动、访问文件或使用功能,并且您在 dmesg 或 logcat 中看到 avc: denied 消息。
[ 123.456] avc: denied { read } for pid=789 comm="my_service" name="some_file" dev="sda1" ino=123 scontext=u:r:my_service_t:s0 tcontext=u:object_r:some_file_t:s0 tclass=file permissive=0
快速调试(仅限开发)
您可以暂时停用 SELinux 强制执行,看看问题是否得到解决。这证实了问题是由于缺少 SELinux 政策规则造成的。
# Disabling SELinux requires root permission
adb root
# Set SELinux to permissive mode
adb shell setenforce 0
# Check the current mode (should return "Permissive")
adb shell getenforce
修复:在拒绝消息中,使用 Android 源代码树中的 audit2allow 工具。这会生成正确的 .te 政策规则,以添加到设备的 SELinux 配置中。