SDV debuggen

Dieser Leitfaden bietet einen Überblick über die wichtigsten Tools und Techniken zum Debuggen von Diensten und Anwendungen, die auf der SDV-Plattform ausgeführt werden.

Mit dem Gerät verbinden

Das wichtigste Tool zum Verbinden mit dem Gerät und zum Interagieren mit ihm ist die Android Debug Bridge (ADB). Prüfen Sie, ob sich adb im Pfad Ihres Systems befindet.

Über das Netzwerk verbinden

Wenn sich das Gerät im selben Netzwerk befindet und Sie die IP-Adresse kennen, können Sie eine Verbindung über Ethernet herstellen. Unser System verwendet ausschließlich Netzwerkverbindungen für adb:

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

Mit mehreren Geräten verbinden

Wenn Sie mehrere Geräte von einer einzigen Workstation aus verwalten möchten, können Sie über verschiedene IP-Adressen eine Verbindung zu ihnen herstellen. Wenn Sie mehrere VMs auf einem einzelnen Host ausführen, müssen Sie jedem Gerät unterschiedliche Ports zuweisen. Dazu muss der adb-Daemon auf jedem SDV-Gerät so konfiguriert werden, dass er auf einem eindeutigen Port lauscht, z. B. 5555 für das erste Gerät und 5556 für das zweite. Sie können den Host auch so konfigurieren, dass diese Ports an verschiedene Gäste weitergeleitet werden:

# 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

Wenn du nachfolgende adb-Befehle ausführst, kannst du ein bestimmtes Gerät mit dem Flag -s und seiner vollständigen Adresse (ip:port) ansprechen:

# Run a shell command on the second VM on first device in the above example
adb -s <device_1_ip_address>:5556 shell

Logs ansehen

Wenn ein Dienst ausfällt oder sich unerwartet verhält, prüfen Sie zuerst die Logs.

Logcat (Android-Logs) verwenden

logcat zeigt Logs von Systemdiensten, Agents und Dienst-Bundles an:

# 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 (Kernel-Logs) verwenden

dmesg zeigt Logs aus dem Linux-Kernel an. Dies ist für die Fehlerbehebung der folgenden Probleme entscheidend:

  • Hardware- und Treiberprobleme
  • Kernel Panics
  • SELinux-Ablehnungen (avc: denied) – auch in logcat angezeigt
# View all kernel messages
adb shell dmesg

# Follow kernel messages in real-time
adb shell dmesg -w

Auf Logs in Cuttlefish zugreifen

Wenn Sie ein virtuelles Cuttlefish-Gerät verwenden, können Sie direkt über das Dateisystem des Hostcomputers auf die Logdateien zugreifen. Das ist besonders nützlich, wenn adb nicht verfügbar ist. Wenn Sie Cuttlefish starten, werden alle Debugging-Pfade ausgegeben. Sie können sie auch mit cvd fleet für alle laufenden Instanzen aufrufen.

  • Logcat (Android-Logs): cuttlefish/instances/cvd-1/logs/logcat
  • Kernel-Logs: cuttlefish/instances/cvd-1/logs/kernel.log
  • Cuttlefish-Launcher-Logs: cuttlefish/instances/cvd-1/logs/launcher.log (hilfreich für die Fehlerbehebung in der Cuttlefish-Umgebung selbst)

Sie können diese Dateien mit Standard-Befehlszeilentools wie cat, less oder tail -f in Echtzeit ansehen.

Mit der Shell und dem Dateisystem interagieren

Shell-Zugriff erhalten, um Befehle direkt auf dem Gerät auszuführen, den Prozessstatus zu prüfen und im Dateisystem zu navigieren:

# 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>

Dateisystemvorgänge ausführen

Verwenden Sie adb push und adb pull, um Dateien zwischen Ihrem Hostcomputer und dem Gerät zu verschieben. Verwenden Sie diese Option, um Testskripts bereitzustellen, die Konfiguration zu aktualisieren oder Crash-Dumps abzurufen:

# 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 .

Anwendungen debuggen (C++/Rust)

Sie können Anwendungen entweder online oder offline debuggen.

lldb für Live-Debugging verwenden

So debuggen Sie einen Dienst in Echtzeit mit lldb (Informationen zum Anhängen des Debuggers aus Android Studio for Platform finden Sie unter Debuggen und testen und Plattformcode debuggen):

  1. Starten Sie adb mit Root-Berechtigungen neu (erforderlich für die Portweiterleitung):

    adb root
    
  2. Wenn eine Binärdatei Debugging-Symbole enthält, übertragen Sie eine nicht gekürzte Version von out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE]. Wenn Sie beispielsweise rpcagent aus system_ext und sdv_core_cf hochladen möchten, führen Sie folgenden Befehl aus:

    adb push out/target/product/sdv_core_cf/symbols/system_ext/bin/rpcagent /data/local/tmp
    
  3. Stellen Sie mit dem LLDB-Client eine Verbindung über das praktische Script lldbclient.py her:

    # 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
    

    Dieses Script stellt eine Remote-Verbindung zu lldb her. Führen Sie lldbclient.py --help aus, um alle verfügbaren Flags aufzurufen.

Crash-Dumps (Tombstones) analysieren

Wenn ein Dienst abstürzt, wird in /data/tombstones/ eine Tombstone-Datei generiert. Die Datei enthält einen Stacktrace, eine Speicherzuordnung und andere wichtige Informationen.

Rufe die Tombstone-Datei ab und analysiere sie dann mit einem symbolfähigen Tool (z. B. lldb oder einem dedizierten Script) und der nicht bereinigten Version der Binärdatei.

Leistung analysieren

SDV unterstützt mehrere Tools für Leistungsmessungen.

CPU- und Arbeitsspeichernutzung prüfen

  • top: Bietet eine Echtzeitansicht der laufenden Prozesse, sortiert nach CPU-Nutzung.

    adb shell top -m 10  # Show top 10 processes
    
  • procrank: Bietet eine detaillierte Aufschlüsselung der Arbeitsspeichernutzung für einen bestimmten Prozess oder das gesamte System.

    adb shell procrank
    

„dumpsys“ für Dienststatus verwenden

dumpsys ist ein leistungsstarkes Tool, mit dem der interne Status eines beliebigen Android-Systemdienstes abgefragt werden kann.

# List all available services
adb shell dumpsys -l

# Dump the state of a specific service or agent
adb shell dumpsys <service_name>

Torq für die Leistungsanalyse verwenden

torq ist ein Befehlszeilentool, das Profilerstellungs- und Tracing-Aufgaben unter Android vereinfacht. Damit können Simpleperf, Perfetto und andere typische Aufgaben während der Analyse der Systemleistung ausgeführt werden.

Perfetto für das Tracing verwenden

Perfetto ist das Standardtool für systemweites Tracing unter Android. Mit Perfetto können Sie Systemereignisse, Trace-Punkte auf Anwendungsebene und Leistungszähler aufzeichnen und auf einer Zeitachse visualisieren.

Wichtige Schritte:

  1. Fügen Sie Ihrem C++- oder Rust-Code Trace-Punkte hinzu:
    • C++: Verwenden Sie das Perfetto SDK mit TRACE_EVENT-Makros.
    • Rust: Verwenden Sie die tracing-Crate, die mit Perfetto kompatible ATrace-Ereignisse ausgibt.
  2. Erstellen Sie eine textproto-Konfigurationsdatei, um Datenquellen (z. B. ftrace, track_event), Kategorien und Tags anzugeben.
  3. Verwenden Sie das Script record_android_trace (external/perfetto/tools/record_android_trace) mit Ihrer Konfigurationsdatei, um den Trace vom Gerät zu erfassen.
  4. Öffnen Sie die generierte Trace-Datei in der Perfetto-Web-UI, um das Systemverhalten zu analysieren, Engpässe zu identifizieren und Dienstinteraktionen zu verstehen.

Eine ausführliche Anleitung zur Instrumentierung, Konfiguration und Erfassung finden Sie unter Tracing verwenden, um Einblicke in die Systemleistung zu erhalten.

Simpleperf für die Profilerstellung verwenden

Simpleperf ist ein vielseitiges Befehlszeilentool für die Leistungsprofilerstellung unter Android, ähnlich wie Linux perf.

Gängige Anwendungsfälle:

  • CPU-Profiling: Funktionen identifizieren, die die meiste CPU-Zeit verbrauchen.
  • Off-CPU-Analyse: Analysieren Sie, warum Threads inaktiv oder blockiert sind.
  • Hardwarezähler: Zugriff auf Hardware-Leistungszähler.

Beispiele für Befehle:

# 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 bietet viele weitere Ereignisse und Optionen. Eine umfassende Dokumentation finden Sie im Simpleperf-Leitfaden.

SELinux-Verweigerungen

Symptom: Ihr Dienst kann nicht gestartet werden, auf eine Datei zugreifen oder eine Funktion verwenden, und Sie sehen eine avc: denied-Meldung in dmesg oder logcat.

[ 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

Schnelles Debugging (nur für die Entwicklung)

Sie können die SELinux-Erzwingung vorübergehend deaktivieren, um zu sehen, ob das Problem dadurch behoben wird. Dies bestätigt, dass das Problem auf eine fehlende SELinux-Richtlinienregel zurückzuführen ist.

# 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

Lösung: Das Tool audit2allow aus dem Android-Quellbaum für die Ablehnungsnachricht. Dadurch wird die richtige .te-Richtlinienregel generiert, die der SELinux-Konfiguration Ihres Geräts hinzugefügt werden soll.