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

複数のデバイスに接続する

1 つのワークステーションから複数のデバイスを管理するには、異なる IP アドレスを使用してデバイスに接続します。単一のホストで複数の VM を実行する場合は、各デバイスに異なるポートを割り当てる必要があります。そのためには、各 SDV デバイスの adb デーモンが一意のポート(たとえば、最初のデバイスは 5555、2 番目のデバイスは 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 コマンドを実行するときに、完全なアドレス(ip:port)とともに -s フラグを使用することで、特定のデバイスをターゲットにできます。

# 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 環境自体のデバッグに役立ちます)

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 を実行してください。lldb に接続するには、IDE のドキュメントをご覧ください。

クラッシュ ダンプ(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++: TRACE_EVENT マクロで Perfetto SDK を使用します。
    • Rust: Perfetto と互換性のある ATrace イベントを発行する tracing クレートを使用します。
  2. テキスト プロトコル構成ファイルを作成して、データソース(ftracetrack_event など)、カテゴリ、タグを指定します。
  3. 構成ファイルで record_android_trace スクリプト(external/perfetto/tools/record_android_trace)を使用して、デバイスからトレースをキャプチャします。
  4. 生成されたトレース ファイルを Perfetto Web UI で開き、システム動作の分析、ボトルネックの特定、サービス間のインタラクションの把握を行います。

計測、構成、収集の詳細な手順については、トレースを使用してシステム パフォーマンスに関する分析情報を取得するをご覧ください。

プロファイリングに Simpleperf を使用する

Simpleperf は、Linux perf に似た、Android でのパフォーマンス プロファイリング用の多用途なコマンドライン ツールです。

一般的なユースケース:

  • 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 または logcatavc: 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 ツール。これにより、デバイスの SELinux 構成に追加する正しい .te ポリシー ルールが生成されます。