Debug di SDV

Questa guida fornisce una panoramica degli strumenti e delle tecniche essenziali per il debug di servizi e applicazioni in esecuzione sulla piattaforma SDV.

Connettersi al dispositivo

Lo strumento principale per connettersi al dispositivo e interagire con esso è Android Debug Bridge (adb). Verifica che adb sia nel percorso del sistema.

Connettersi tramite la rete

Se il dispositivo si trova sulla stessa rete e conosci il suo indirizzo IP, puoi connetterti tramite Ethernet. Il nostro sistema utilizza esclusivamente le connessioni di rete per adb:

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

Connettersi a più dispositivi

Per gestire più dispositivi da una singola workstation, puoi connetterti a questi tramite indirizzi IP diversi. Se esegui più VM su un singolo host, devi assegnare porte diverse a ogni dispositivo. Per farlo, devi configurare il daemon adb su ogni dispositivo SDV in modo che sia in ascolto su una porta univoca, ad esempio 5555 per il primo dispositivo e 5556 per il secondo. Puoi anche configurare l'host in modo che inoltri queste porte a ospiti diversi:

# 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

Quando esegui i comandi adb successivi, puoi scegliere come target un dispositivo specifico utilizzando il flag -s con il suo indirizzo completo (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

Visualizzare i log

Se un servizio non funziona o si comporta in modo imprevisto, controlla prima i log.

Utilizzare logcat (log di Android)

logcat mostra i log dei servizi di sistema, degli agenti e dei bundle di servizi:

# 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

Utilizzare dmesg (log del kernel)

dmesg mostra i log del kernel Linux. È fondamentale per il debug di quanto segue:

  • Problemi relativi a hardware e driver
  • Kernel panic
  • Negazioni SELinux (avc: denied) - visualizzate anche in logcat
# View all kernel messages
adb shell dmesg

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

Accedere ai log su Cuttlefish

Quando esegui un dispositivo virtuale Cuttlefish, puoi accedere direttamente ai file di log dal file system della macchina host. È particolarmente utile se adb non è disponibile. Quando avvii Cuttlefish, vengono visualizzati tutti i percorsi di debug. Puoi anche cercarli utilizzando cvd fleet per tutte le istanze in esecuzione.

  • Logcat (log di Android): cuttlefish/instances/cvd-1/logs/logcat
  • Log del kernel: cuttlefish/instances/cvd-1/logs/kernel.log
  • Log del launcher Cuttlefish: cuttlefish/instances/cvd-1/logs/launcher.log (utile per il debug dell'ambiente Cuttlefish stesso)

Puoi utilizzare strumenti a riga di comando standard come cat, less o tail -f per visualizzare questi file in tempo reale.

Interagire con la shell e il file system

Ottieni l'accesso alla shell per eseguire i comandi direttamente sul dispositivo, controllare lo stato dei processi e navigare nel file system:

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

Eseguire operazioni sul file system

Utilizza adb push e adb pull per spostare i file tra la macchina host e il dispositivo. Utilizza questa opzione per eseguire il deployment degli script di test, aggiornare la configurazione o recuperare i dump di arresto anomalo:

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

Eseguire il debug delle applicazioni (C++/Rust)

Puoi eseguire il debug delle applicazioni online o offline.

Utilizzare lldb per il debug live

lldb è il debugger predefinito in Android Studio ed è spesso preferito per lo sviluppo moderno in C++ e Rust.

Segui questi passaggi di configurazione:

  1. Riavvia adb per consentire le autorizzazioni di root (necessarie per l'inoltro). Utilizza questa opzione per configurare l'inoltro delle porte. Sull'host, esegui:

    adb root
    
  2. Se un file binario ha simboli di debug, esegui il push di una versione non eliminata. Puoi trovare la versione non eliminata in out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE]. Ad esempio, per caricare rpcagent da system_ext e sdv_core_cf, esegui:

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

    Ora la versione non eliminata si trova in /data/local/tmp.

  3. Connettiti con il client LLDB utilizzando lo script di convenienza lldbclient.py:

    # 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
    

    Questo script connette lldb da remoto. Per tutti i flag disponibili, esegui lldbclient.py. Consulta la documentazione dell'IDE per connetterlo a lldb.

Analizzare i dump di arresto anomalo (tombstones)

Quando un servizio si arresta in modo anomalo, viene generato un file tombstone in /data/tombstones/. Il file contiene un'analisi dello stack, una mappa della memoria e altre informazioni cruciali.

Esegui il pull del file tombstone, quindi utilizza uno strumento che riconosce i simboli (come lldb o uno script dedicato) per analizzarlo con la versione non eliminata del file binario.

Analizzare il rendimento

SDV supporta più strumenti per le misurazioni del rendimento.

Controllare l'utilizzo di CPU e memoria

  • top: fornisce una visualizzazione in tempo reale dei processi in esecuzione ordinati in base all'utilizzo della CPU.

    adb shell top -m 10  # Show top 10 processes
    
  • procrank: fornisce una suddivisione dettagliata della memoria utilizzata per un processo specifico o per l'intero sistema.

    adb shell procrank
    

Utilizzare dumpsys per lo stato del servizio

dumpsys è uno strumento potente per eseguire query sullo stato interno di qualsiasi servizio di sistema Android.

# List all available services
adb shell dumpsys -l

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

Utilizzare torq per l'analisi del rendimento

torq è uno strumento a riga di comando che semplifica le attività di profilazione e tracciamento su Android. Consente di eseguire Simpleperf, Perfetto e altre attività tipiche durante l'analisi del rendimento del sistema.

Utilizzare Perfetto per il tracciamento

Perfetto è lo strumento standard per il tracciamento a livello di sistema su Android. Perfetto consente di registrare gli eventi di sistema, i punti di traccia a livello di app e i contatori di rendimento e di visualizzarli su una sequenza temporale.

Passaggi chiave:

  1. Aggiungi punti di traccia nel codice C++ o Rust:
    • C++: utilizza l'SDK Perfetto con le macro TRACE_EVENT.
    • Rust: utilizza la crate tracing, che genera eventi ATrace compatibili con Perfetto.
  2. Crea un file di configurazione textproto per specificare origini dati (ad esempio, ftrace, track_event), categorie e tag.
  3. Utilizza lo script record_android_trace (external/perfetto/tools/record_android_trace) con il file di configurazione per acquisire la traccia dal dispositivo.
  4. Apri il file di traccia generato nell'interfaccia utente web di Perfetto per analizzare il comportamento del sistema , identificare i colli di bottiglia e comprendere le interazioni dei servizi.

Per istruzioni dettagliate su strumentazione, configurazione e raccolta, consulta Utilizzare il tracciamento per ottenere informazioni sul rendimento del sistema.

Utilizzare Simpleperf per la profilazione

Simpleperf è uno strumento a riga di comando versatile per la profilazione del rendimento su Android, simile a Linux perf.

Casi d'uso comuni:

  • Profilazione della CPU: identifica le funzioni che consumano più tempo della CPU.
  • Analisi off-CPU: analizza perché i thread sono inattivi o bloccati.
  • Contatori hardware: accedi ai contatori di rendimento hardware.

Comandi di esempio:

# 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 offre molti altri eventi e opzioni. Per una documentazione completa, consulta la guida di Simpleperf.

Negazioni SELinux

Sintomo: il servizio non viene avviato, non accede a un file o non utilizza una funzionalità, e viene visualizzato un messaggio avc: denied in dmesg o 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

Debug rapido (solo per lo sviluppo)

Puoi disattivare temporaneamente l'applicazione di SELinux per verificare se il problema si risolve. In questo modo, confermi che il problema è dovuto a una regola delle policy SELinux mancante.

# 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

Soluzione: lo strumento audit2allow dall'albero di origine Android sul messaggio di negazione. In questo modo viene generata la regola delle policy .te corretta da aggiungere alla configurazione SELinux del dispositivo.