SDV debuggen

In diesem Leitfaden finden Sie eine Übersicht über die wichtigsten Tools und Techniken zur Fehlerbehebung bei Diensten und Anwendungen, die auf der SDV-Plattform ausgeführt werden.

Verbindung zum Gerät herstellen

Das primäre Tool zum Herstellen einer Verbindung zum Gerät und zur Interaktion mit dem Gerät 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 seine IP-Adresse kennen, können Sie eine Ethernet-Verbindung 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

Verbindung zu mehreren Geräten herstellen

Wenn Sie mehrere Geräte von einer einzelnen 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 wartet, 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 Sie nachfolgende adb-Befehle ausführen, können Sie mit dem Flag -s und der vollständigen Adresse (ip:port) ein bestimmtes Gerät auswählen:

# 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 fehlschlägt oder sich unerwartet verhält, prüfen Sie zuerst die Logs.

Logcat verwenden (Android-Logs)

logcat zeigt Logs von Systemdiensten, Agents und Dienstpaketen 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 verwenden (Kernel-Logs)

dmesg zeigt Logs aus dem Linux-Kernel an. Dies ist entscheidend für die Fehlerbehebung bei Folgendem:

  • Hardware- und Treiberprobleme
  • Kernel Panics
  • SELinux-Verweigerungen (avc: denied) – werden 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 auf einem virtuellen Cuttlefish-Gerät ausgeführt werden, können Sie direkt über das Dateisystem des Hostcomputers auf die Logdateien zugreifen. Dies 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 ausgeführten Instanzen nachschlagen.

  • 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 (nützlich für die Fehlerbehebung in der Cuttlefish-Umgebung selbst)

Sie können Standard-Befehlszeilentools wie cat, less oder tail -f verwenden, um diese Dateien in Echtzeit anzusehen.

Mit der Shell und dem Dateisystem interagieren

Sie können auf die Shell zugreifen, 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

Mit adb push und adb pull können Sie Dateien zwischen Ihrem Hostcomputer und dem Gerät verschieben. Verwenden Sie diese Befehle, um Testskripts bereitzustellen, die Konfiguration zu aktualisieren oder Absturz-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 .

Fehlerbehebung bei Anwendungen (C++/Rust)

Sie können die Fehlerbehebung bei Anwendungen entweder online oder offline durchführen.

lldb für die Live-Fehlerbehebung verwenden

lldb ist der Standard-Debugger in Android Studio und wird häufig für die moderne C++- und Rust-Entwicklung bevorzugt.

Führen Sie die folgenden Einrichtungsschritte aus:

  1. Starten Sie adb neu, um Root-Berechtigungen zuzulassen (erforderlich für die Weiterleitung). Verwenden Sie diesen Befehl, um die Portweiterleitung einzurichten. Führen Sie auf dem Host folgenden Befehl aus:

    adb root
    
  2. Wenn eine Binärdatei Debugging-Symbole enthält, übertragen Sie eine nicht reduzierte Version. Sie finden die nicht reduzierte Version unter out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE]. Führen Sie beispielsweise die folgenden Befehle aus, um rpcagent von system_ext und sdv_core_cf hochzuladen:

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

    Die nicht reduzierte Version befindet sich jetzt in /data/local/tmp.

  3. Stellen Sie mit dem praktischen Skript lldbclient.py eine Verbindung mit dem LLDB-Client 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 Skript stellt eine Remote-Verbindung zu lldb her. Führen Sie lldbclient.py aus, um alle verfügbaren Flags aufzurufen. Informationen zum Herstellen einer Verbindung zur IDE finden Sie in der Dokumentation.

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

Rufen Sie die Tombstone-Datei ab und analysieren Sie sie dann mit einem symbolfähigen Tool (z. B. lldb oder einem speziellen Skript) mit der nicht reduzierten Version der Binärdatei.

Leistung analysieren

SDV unterstützt mehrere Tools für Leistungsmessungen.

CPU- und Arbeitsspeichernutzung prüfen

  • top: Bietet eine Echtzeitansicht der ausgeführten 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 den Dienststatus verwenden

dumpsys ist ein leistungsstarkes Tool zum Abfragen des internen Status eines beliebigen Android-Systemdienstes.

# 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 Profiling- und Tracing-Aufgaben unter Android vereinfacht. Damit können Sie Simpleperf, Perfetto und andere typische Aufgaben während der Systemleistungsanalyse ausführen.

Perfetto für das Tracing verwenden

Perfetto ist das Standardtool für das systemweite Tracing unter Android. Mit Perfetto können Sie Systemereignisse, Tracepoints auf App-Ebene und Leistungszähler aufzeichnen und auf einer Zeitachse visualisieren.

Wichtige Schritte :

  1. Fügen Sie Tracepoints in Ihrem C++- oder Rust-Code hinzu:
    • C++:Verwenden Sie das Perfetto SDK mit TRACE_EVENT-Makros.
    • Rust:Verwenden Sie das tracing-Crate, das 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 Skript 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 Tracedatei in der Perfetto-Web-UI, um das Systemverhalten zu analysieren, Engpässe zu identifizieren und Dienstinteraktionen zu verstehen.

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

Simpleperf für das Profiling verwenden

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

Gängige Anwendungsfälle:

  • CPU-Profiling: Funktionen identifizieren, die die meiste CPU-Zeit verbrauchen.
  • Off-CPU-Analyse: Analysieren, warum Threads im Leerlauf sind oder blockiert werden.
  • Hardwarezähler: Auf Hardware-Leistungszähler zugreifen.

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 in dmesg oder logcat die Meldung 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

Schnelle Fehlerbehebung (nur für die Entwicklung)

Sie können die SELinux-Erzwingung vorübergehend deaktivieren, um zu prüfen, ob das Problem dadurch behoben wird. So können Sie bestätigen, 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

Problemlösung: Verwenden Sie das audit2allow Tool aus dem Android-Quellcodebaum für die Verweigerung smeldung. Dadurch wird die richtige .te-Richtlinienregel generiert, die Sie der SELinux-Konfiguration Ihres Geräts hinzufügen können.