偵錯來源文件驗證 (SDV)

本指南概略說明在 SDV 平台上偵錯服務和應用程式時,所需的重要工具和技術。

連線至裝置

Android Debug Bridge (ADB) 是連線至裝置並與其互動的主要工具。確認 adb 位於系統路徑中。

使用網路連線

如果裝置位於相同網路,且您知道其 IP 位址,則可透過乙太網路連線。系統只會使用網路連線進行 ADB:

# Connect to the device using its IP address and default port
adb connect <device_ip_address>:5555

連線到多部裝置

如要從單一工作站管理多部裝置,可以透過不同的 IP 位址連線。如果您在單一主機上執行多個 VM,則必須為每部裝置指派不同的通訊埠。這需要設定每個 SDV 裝置上的 ADB Daemon,監聽不重複的通訊埠,例如第一個裝置為 5555,第二個裝置為 5556。您也可以設定主機,將這些通訊埠轉送至不同的訪客:

# 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 等標準指令列工具,即時查看這些檔案。

與殼層和檔案系統互動

取得殼層存取權,直接在裝置上執行指令、檢查程序狀態,以及瀏覽檔案系統:

# 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 在主機和裝置之間移動檔案。您可以使用這項功能部署測試指令碼、更新設定,或擷取當機 dump 檔:

# 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 for Platform 附加偵錯工具,請參閱「偵錯和測試」和「偵錯平台程式碼」):

  1. 以 root 權限重新啟動 adb (通訊埠轉送需要):

    adb root
    
  2. 如果二進位檔有偵錯符號,請從 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
    
  3. 使用 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 --help。

分析當機 dump 檔 (tombstone)

服務當機時,系統會在 /data/tombstones/ 中產生墓碑檔案。檔案包含堆疊追蹤、記憶體對應和其他重要資訊。

提取 Tombstone 檔案,然後使用符號感知工具 (例如 lldb 或專用指令碼),搭配未去除符號的二進位檔版本進行分析。

分析效能

SDV 支援多種效能評估工具。

查看 CPU 和記憶體用量

  • top:即時顯示執行中的程序,並依 CPU 使用率排序。

    adb shell top -m 10  # Show top 10 processes
    
  • procrank:提供特定程序或整個系統的記憶體用量詳細分析。

    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 可讓您記錄系統事件、應用程式層級追蹤點和效能計數器,並在時間軸上以視覺化方式呈現。

主要步驟:

  1. 在 C++ 或 Rust 程式碼中新增追蹤點:
    • C++:搭配使用 Perfetto SDK 和 TRACE_EVENT 巨集。
    • Rust:使用 tracing crate,其會發出與 Perfetto 相容的 ATrace 事件。
  2. 建立 textproto 設定檔,指定資料來源 (例如 ftrace、track_event)、類別和標記。
  3. 使用 record_android_trace 指令碼 (external/perfetto/tools/record_android_trace) 和設定檔,從裝置擷取追蹤記錄。
  4. 在 Perfetto 網頁 UI 中開啟產生的追蹤記錄檔,分析系統行為、找出瓶頸,並瞭解服務互動情形。

如需檢測、設定和收集的詳細操作說明,請參閱「使用追蹤功能深入瞭解系統效能」。

使用 Simpleperf 進行分析

Simpleperf 是一款多功能指令列工具,可用於分析 Android 效能,類似 Linux perf。

常見用途:

  • CPU 分析:找出耗用最多 CPU 作業時間的函式。
  • 非 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 設定。