Depura la SDV

En esta guía, se proporciona una descripción general de las herramientas y técnicas esenciales para depurar servicios y aplicaciones que se ejecutan en la plataforma de SDV.

Conéctate al dispositivo

La herramienta principal para conectarse con el dispositivo y para interactuar con él es Android Debug Bridge (adb). Verifica que adb esté en la ruta de acceso del sistema.

Conéctate a través de la red

Si el dispositivo está en la misma red y conoces su dirección IP, puedes conectarte por Ethernet. Nuestro sistema usa exclusivamente conexiones de red para adb:

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

Conectarse a varios dispositivos

Para administrar varios dispositivos desde una sola estación de trabajo, puedes conectarte a ellos a través de diferentes direcciones IP. Si ejecutas varias VMs en un solo host, debes asignar puertos diferentes a cada dispositivo. Esto requiere configurar el daemon de adb en cada dispositivo SDV para que escuche en un puerto único, por ejemplo, 5555 para el primer dispositivo y 5556 para el segundo. También puedes configurar el host para que reenvíe esos puertos a diferentes invitados:

# 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

Cuando ejecutes comandos adb posteriores, puedes segmentar un dispositivo específico con la marca -s y su dirección completa (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

Ver registros

Cuando un servicio falla o se comporta de forma inesperada, primero verifica los registros.

Usa logcat (registros de Android)

logcat muestra registros de servicios del sistema, agentes y paquetes de servicios:

# 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

Usa dmesg (registros del kernel)

dmesg muestra registros del kernel de Linux. Esto es fundamental para depurar lo siguiente:

  • Problemas de hardware y controladores
  • Errores irrecuperables del kernel
  • Rechazos de SELinux (avc: denied): También se muestran en Logcat.
# View all kernel messages
adb shell dmesg

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

Registros de acceso en Cuttlefish

Cuando ejecutas en un dispositivo virtual de Cuttlefish, puedes acceder directamente a los archivos de registro desde el sistema de archivos de la máquina host. Esto es especialmente útil si adb no está disponible. Cuando inicias Cuttlefish, se generan todas las rutas de depuración, y también puedes buscarlas con cvd fleet para todas las instancias en ejecución.

  • Logcat (registros de Android): cuttlefish/instances/cvd-1/logs/logcat
  • Registros del kernel: cuttlefish/instances/cvd-1/logs/kernel.log
  • Registros del iniciador de Cuttlefish: cuttlefish/instances/cvd-1/logs/launcher.log (útiles para depurar el entorno de Cuttlefish)

Puedes usar herramientas de línea de comandos estándar, como cat, less o tail -f, para ver estos archivos en tiempo real.

Interactúa con el shell y el sistema de archivos

Obtén acceso al shell para ejecutar comandos directamente en el dispositivo, verificar el estado del proceso y navegar por el sistema de archivos:

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

Realizar operaciones del sistema de archivos

Usa adb push y adb pull para mover archivos entre tu máquina anfitrión y el dispositivo. Usa esta opción para implementar secuencias de comandos de prueba, actualizar la configuración o recuperar volcados de memoria por fallas:

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

Depura aplicaciones (C++/Rust)

Puedes depurar aplicaciones en línea o sin conexión.

Cómo usar lldb para la depuración en vivo

lldb es el depurador predeterminado en Android Studio y, a menudo, se prefiere para el desarrollo moderno en C++ y Rust.

Sigue estos pasos de configuración:

  1. Reinicia adb para permitir permisos de administrador (necesarios para el reenvío). Usa esto para configurar el reenvío de puertos. En el host, ejecuta lo siguiente:

    adb root
    
  2. Si un objeto binario tiene símbolos de depuración, envía una versión sin quitar. Puedes encontrar la versión sin quitar en out/target/product/[SDV_FLAVOR]/symbols/[PARTITION]/bin/[EXECUTABLE]. Por ejemplo, para subir rpcagent desde system_ext y sdv_core_cf, ejecuta el siguiente comando:

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

    Ahora, la versión sin quitar está en /data/local/tmp.

  3. Conéctate con el cliente de LLDB usando la secuencia de comandos de conveniencia 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
    

    Esta secuencia de comandos conecta lldb de forma remota. Para ver todas las marcas disponibles, ejecuta lldbclient.py. Consulta la documentación de tu IDE para conectarlo a lldb.

Analiza los volcados de memoria de fallas (lápidas)

Cuando falla un servicio, se genera un archivo de lápida en /data/tombstones/. El archivo contiene un seguimiento de pila, un mapa de memoria y otra información crucial.

Extrae el archivo de marcas de depuración y, luego, usa una herramienta que tenga en cuenta los símbolos (como lldb o una secuencia de comandos dedicada) para analizarlo con la versión sin quitar del archivo binario.

Analiza el rendimiento

SDV admite varias herramientas para las mediciones de rendimiento.

Verifica el uso de la CPU y la memoria

  • top: Proporciona una vista en tiempo real de los procesos en ejecución ordenados por uso de CPU.

    adb shell top -m 10  # Show top 10 processes
    
  • procrank: Proporciona un desglose detallado del uso de la memoria para un proceso específico o para todo el sistema.

    adb shell procrank
    

Usa dumpsys para el estado del servicio

dumpsys es una herramienta potente para consultar el estado interno de cualquier servicio del sistema Android.

# List all available services
adb shell dumpsys -l

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

Usa torq para el análisis de rendimiento

torq es una herramienta de línea de comandos que simplifica las tareas de generación de perfiles y seguimiento en Android. Permite ejecutar Simpleperf, Perfetto y otras tareas típicas durante el análisis del rendimiento del sistema.

Usa Perfetto para el registro

Perfetto es la herramienta estándar para el registro en todo el sistema en Android. Perfetto te permite registrar eventos del sistema, puntos de registro a nivel de la app y contadores de rendimiento, y visualizarlos en un cronograma.

Pasos clave:

  1. Agrega puntos de registro en tu código C++ o Rust:
    • C++: Usa el SDK de Perfetto con macros de TRACE_EVENT.
    • Rust: Usa el crate tracing, que emite eventos de ATrace compatibles con Perfetto.
  2. Crea un archivo de configuración textproto para especificar fuentes de datos (por ejemplo, ftrace, track_event), categorías y etiquetas.
  3. Usa la secuencia de comandos record_android_trace (external/perfetto/tools/record_android_trace) con tu archivo de configuración para capturar el registro del dispositivo.
  4. Abre el archivo de registro generado en la IU web de Perfetto para analizar el comportamiento del sistema, identificar cuellos de botella y comprender las interacciones del servicio.

Para obtener instrucciones detalladas sobre la instrumentación, la configuración y la recopilación, consulta Usa el registro para obtener estadísticas sobre el rendimiento del sistema.

Cómo usar Simpleperf para la generación de perfiles

Simpleperf es una herramienta de línea de comandos versátil para la generación de perfiles de rendimiento en Android, similar a Linux perf.

Casos prácticos habituales:

  • Creación de perfiles de CPU: Identifica las funciones que consumen la mayor cantidad de tiempo de CPU.
  • Análisis fuera de la CPU: Analiza por qué los subprocesos están inactivos o bloqueados.
  • Contadores de hardware: Accede a los contadores de rendimiento del hardware.

Comandos de ejemplo:

# 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 ofrece muchos más eventos y opciones. Consulta la guía de Simpleperf para obtener documentación completa.

Rechazos de SELinux

Síntoma: Tu servicio no se inicia, no puede acceder a un archivo o no puede usar una capacidad, y ves un mensaje de avc: denied en 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

Depuración rápida (solo para desarrollo)

Puedes inhabilitar temporalmente la aplicación de SELinux para ver si se resuelve el problema. Esto confirma que el problema se debe a la falta de una regla de política de 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

Corrección: La herramienta audit2allow del árbol de fuentes de Android en el mensaje de rechazo. Esto genera la regla de política .te correcta para agregar a la configuración de SELinux de tu dispositivo.