偵錯來源文件驗證 (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 查詢所有執行中的執行個體。

cvd-1cvd-X
  • Logcat (Android 記錄): cuttlefish/instances/cvd-1/logs/logcat
  • 核心記錄: cuttlefish/instances/cvd-1/logs/kernel.log
  • Cuttlefish 啟動器記錄: cuttlefish/instances/cvd-1/logs/launcher.log (有助於偵錯 Cuttlefish 環境本身)
  • 您可以使用 catlesstail -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 pushadb 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 開發作業的首選工具。

    按照下列設定步驟操作:

    1. 重新啟動 adb,允許根層級權限 (轉送時必須具備這項權限)。使用這項功能設定通訊埠轉送。在主機上執行:

      adb root
      
    2. 如果二進位檔有除錯符號,請推送未經剝除的版本。 您可以在 out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE] 中找到未經剝除的版本。舉例來說,如要從 system_extsdv_core_cf 上傳 rpcagent,請執行:

      adb push out/target/product/sdv_core_cf/symbols/system_ext/bin/rpcagent /data/local/tmp
      

      現在未經剝除的版本位於 /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。請參閱 IDE 說明文件,瞭解如何將 IDE 連線至 lldb。

    分析當機傾印 (墓碑)

    服務當機時,系統會在 /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 設定檔,指定資料來源 (例如 ftracetrack_event)、類別和標記。
    3. 使用 record_android_trace 指令碼 (external/perfetto/tools/record_android_trace) 和設定檔,從裝置擷取追蹤記錄。
    4. Perfetto Web 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 拒絕

    問題:服務無法啟動、存取檔案或使用功能,且您在 dmesglogcat 中看到 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 設定。