← Volver al listado de tecnologías
Capítulo 2: Conceptos Básicos y Arquitectura de ADB
Capítulo 2: Conceptos Básicos y Arquitectura de ADB
Este capítulo explora en profundidad cómo funciona ADB internamente, su arquitectura de tres componentes, los protocolos de comunicación y los diferentes modos de conexión disponibles.
🎯 Objetivos del Capítulo
Al finalizar este capítulo comprenderás:
- ✅ La arquitectura cliente-servidor-daemon de ADB
- ✅ Cómo se comunican los componentes entre sí
- ✅ Los protocolos y puertos utilizados
- ✅ Diferencias entre conexión USB, WiFi y Ethernet
- ✅ El ciclo de vida de una sesión ADB
- ✅ Seguridad y autenticación RSA
🏗️ Arquitectura de ADB
Los Tres Componentes
1. Cliente ADB:
- Ubicación: Tu computadora
- Función: Interfaz de línea de comandos
- Puerto: Se conecta al servidor en 5037
- Ejemplos: adb shell, adb install, adb push
2. Servidor ADB (adb server):
- Ubicación: Tu computadora (proceso en background)
- Función: Gestiona comunicación cliente-dispositivo
- Puerto: Escucha en TCP 5037
- Proceso: adb.exe (Windows) o adb (Unix)
3. Daemon ADB (adbd):
- Ubicación: Dispositivo Android
- Función: Ejecuta comandos en el dispositivo
- Puerto: 5555 (WiFi) o USB
- Proceso: /system/bin/adbd
Diagrama de Comunicación
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Cliente │ │ Servidor │ │ Daemon │
│ ADB │◄────►│ ADB │◄────►│ (adbd) │
│ (CLI) │ TCP │ (PC:5037) │ USB/ │ (Android) │
└─────────────┘ └─────────────┘ WiFi └─────────────┘
Tu PC Tu PC Tu Dispositivo
Flujo de Comunicación Detallado
// Cuando ejecutas: adb shell ls /sdcard
// 1. Cliente verifica servidor
client.checkServer() {
try {
connect("localhost:5037")
} catch {
startServer() // Auto-inicia si no está corriendo
}
}
// 2. Cliente envía comando al servidor
client.sendCommand("host:transport-usb")
client.sendCommand("shell:ls /sdcard")
// 3. Servidor reenvía al daemon
server.forwardToDevice(deviceId, "shell:ls /sdcard")
// 4. Daemon ejecuta en dispositivo
adbd.execute("ls /sdcard")
// 5. Respuesta viaja de vuelta
adbd → server → client → pantalla
🖥️ El Servidor ADB
Ciclo de Vida del Servidor
# Estado inicial: servidor no está corriendo
$ adb devices
* daemon not running; starting now at tcp:5037
* daemon started successfully
# El servidor ahora está escuchando
$ netstat -an | grep 5037
tcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN
# Verificar proceso
$ ps aux | grep adb
user 12345 0.0 0.1 adb fork-server server
# Detener servidor manualmente
$ adb kill-server
# El servidor se auto-inicia cuando es necesario
$ adb devices # Auto-inicia el servidor
Configuración del Servidor
# Puerto personalizado
export ADB_SERVER_PORT=5038
adb -P 5038 start-server
# Configuración de timeout
export ADB_TRACE=all # Debug completo
export ADB_VENDOR_KEYS=$HOME/.android # Claves vendor
# Archivo de configuración global
# ~/.android/adb_usb.ini
# Contiene Vendor IDs adicionales
0x2717 # Xiaomi
0x2a70 # OnePlus
Gestión de Múltiples Dispositivos
# Cómo el servidor maneja múltiples dispositivos
class ADBServer:
def __init__(self):
self.devices = {} # {serial: connection}
self.port = 5037
def handle_client_request(self, request):
if request.startswith("host:"):
# Comandos del servidor
return self.handle_host_command(request)
elif request.startswith("host-serial:"):
# Comando para dispositivo específico
serial = self.extract_serial(request)
return self.forward_to_device(serial, request)
elif request.startswith("host:transport"):
# Seleccionar dispositivo para comandos siguientes
self.select_device(request)
📱 El Daemon (adbd)
Ubicación y Permisos
# Ubicación del daemon
$ adb shell ls -la /system/bin/adbd
-rwxr-xr-x 1 root shell 334408 2024-01-01 00:00 /system/bin/adbd
# Proceso en ejecución
$ adb shell ps | grep adbd
shell 1234 1 19264 1620 poll_schedule_timeout S adbd
# Propiedades relacionadas
$ adb shell getprop | grep adb
[init.svc.adbd]: [running]
[persist.adb.tcp.port]: [5555]
[ro.adb.secure]: [1] # ADB seguro habilitado
[sys.usb.config]: [adb]
[sys.usb.state]: [adb]
Modos de Operación del Daemon
USB Mode (Por defecto):
- Conexión: Cable USB
- Configuración: sys.usb.config=adb
- Seguridad: Requiere autorización RSA
- Velocidad: Más rápida y estable
TCP/IP Mode (WiFi):
- Conexión: Red WiFi
- Puerto: 5555 (configurable)
- Comando: adb tcpip 5555
- Seguridad: Menos segura (sin cable físico)
Root Mode:
- Solo en builds userdebug/eng
- Comando: adb root
- Reinicia adbd como root
- Acceso completo al sistema
Control del Daemon
# Reiniciar daemon en el dispositivo
$ adb shell "stop adbd && start adbd"
# Cambiar a modo TCP/IP
$ adb shell setprop service.adb.tcp.port 5555
$ adb shell "stop adbd && start adbd"
# Verificar estado
$ adb shell getprop init.svc.adbd
running
# Ver logs del daemon
$ adb shell logcat -s adbd
🔐 Autenticación RSA
Proceso de Autorización
# Flujo de autenticación RSA
def authenticate_device():
# 1. Cliente genera par de claves RSA (si no existe)
if not exists("~/.android/adbkey"):
generate_rsa_keypair()
# 2. Servidor envía clave pública al dispositivo
public_key = read_file("~/.android/adbkey.pub")
send_to_device("AUTH", public_key)
# 3. Dispositivo muestra prompt al usuario
# "¿Permitir depuración USB?"
# "Huella digital RSA: XX:XX:XX:XX..."
# 4. Usuario acepta
if user_accepts():
# Clave se guarda en dispositivo
save_to_file("/data/misc/adb/adb_keys", public_key)
return "authorized"
else:
return "unauthorized"
Ubicación de Claves
# En tu computadora
~/.android/adbkey # Clave privada
~/.android/adbkey.pub # Clave pública
# En Windows
%USERPROFILE%\.android\adbkey
%USERPROFILE%\.android\adbkey.pub
# En el dispositivo Android
/data/misc/adb/adb_keys # Claves autorizadas
# Ver claves autorizadas en dispositivo (requiere root)
$ adb shell su -c "cat /data/misc/adb/adb_keys"
# Revocar todas las autorizaciones
# Ajustes → Opciones de desarrollador → Revocar autorizaciones USB
🔌 Modos de Conexión
Conexión USB
// Configuración USB
const usbConfig = {
mode: "MTP", // Media Transfer Protocol
speed: "USB 3.0", // Hasta 5 Gbps
power: "500mA", // Alimentación estándar
advantages: [
"Más rápida y estable",
"Conexión segura (cable físico)",
"No requiere red",
"Carga el dispositivo"
],
disadvantages: [
"Requiere cable",
"Limitado por longitud del cable",
"Un dispositivo por puerto USB"
]
};
// Detección USB
$ lsusb | grep -i android
Bus 001 Device 004: ID 18d1:4ee7 Google Inc. Nexus/Pixel Device
// Verificar conexión USB
$ adb shell getprop sys.usb.state
adb
Conexión WiFi
# Configuración inicial (requiere USB primero)
# 1. Conectar por USB
$ adb devices
# 2. Habilitar TCP/IP
$ adb tcpip 5555
restarting in TCP mode port: 5555
# 3. Obtener IP del dispositivo
$ adb shell ip addr show wlan0
inet 192.168.1.100/24 brd 192.168.1.255
# 4. Conectar por WiFi
$ adb connect 192.168.1.100:5555
connected to 192.168.1.100:5555
# 5. Desconectar USB (opcional)
# Ya puedes trabajar sin cables
# Verificar conexión
$ adb devices
192.168.1.100:5555 device
# Configuración persistente (requiere root)
$ adb shell su -c "setprop persist.adb.tcp.port 5555"
Conexión Ethernet
# Para dispositivos con puerto Ethernet o adaptador USB-Ethernet
# Similar a WiFi pero más estable
# 1. Obtener IP Ethernet
$ adb shell ip addr show eth0
inet 192.168.1.200/24
# 2. Habilitar TCP/IP
$ adb tcpip 5555
# 3. Conectar
$ adb connect 192.168.1.200:5555
# Ventajas sobre WiFi:
# - Conexión más estable
# - Mayor velocidad
# - Menor latencia
# - Ideal para CI/CD
Wireless Debugging (Android 11+)
# Android 11 introdujo Wireless Debugging nativo
# En el dispositivo:
# Ajustes → Opciones de desarrollador → Depuración inalámbrica
# Opción 1: Pairing con código
$ adb pair 192.168.1.100:37853
Enter pairing code: 123456
Successfully paired to 192.168.1.100:37853
# Opción 2: QR Code
$ adb pair --qr-code
# Escanear QR con el dispositivo
# Conectar después del pairing
$ adb connect 192.168.1.100:39875
connected to 192.168.1.100:39875
# Ventajas:
# - No requiere cable USB inicial
# - Más seguro (pairing code)
# - Integrado en Android
📊 Protocolos y Comunicación
Protocolo ADB
# Estructura de mensajes ADB
class ADBMessage:
def __init__(self):
self.command = 4 # bytes: CNXN, OPEN, OKAY, CLSE, WRTE
self.arg0 = 4 # bytes: primer argumento
self.arg1 = 4 # bytes: segundo argumento
self.data_length = 4 # bytes: longitud de datos
self.data_crc32 = 4 # bytes: checksum
self.magic = 4 # bytes: command ^ 0xFFFFFFFF
# Comandos principales
COMMANDS = {
"CNXN": 0x4e584e43, # Conexión
"OPEN": 0x4e45504f, # Abrir stream
"OKAY": 0x59414b4f, # Confirmación
"CLSE": 0x45534c43, # Cerrar stream
"WRTE": 0x45545257, # Escribir datos
"AUTH": 0x48545541, # Autenticación
"SYNC": 0x434e5953, # Sincronización
}
Servicios Disponibles
# Servicios que el daemon puede ejecutar
shell:comando # Ejecutar comando shell
sync: # Sincronización de archivos
tcp:puerto # Reenvío de puerto TCP
local:socket # Socket local Unix
localreserved:socket # Socket reservado
localabstract:socket # Socket abstracto
jdwp:pid # Java Debug Wire Protocol
track-jdwp # Rastrear procesos JDWP
reverse:comando # Reenvío inverso
Port Forwarding
# Reenviar puerto local al dispositivo
$ adb forward tcp:8080 tcp:8080
# Ahora localhost:8080 → dispositivo:8080
# Reenviar a socket Unix
$ adb forward tcp:9999 localabstract:chrome_devtools_remote
# Ver reenvíos activos
$ adb forward --list
ABC123DEF456 tcp:8080 tcp:8080
ABC123DEF456 tcp:9999 localabstract:chrome_devtools_remote
# Eliminar reenvío
$ adb forward --remove tcp:8080
$ adb forward --remove-all
# Reverse forwarding (dispositivo → PC)
$ adb reverse tcp:3000 tcp:3000
# El dispositivo puede acceder a localhost:3000 del PC
🔍 Debugging de ADB
Variables de Entorno para Debug
# Activar logging completo
export ADB_TRACE=all
adb devices
# Niveles de trace específicos
export ADB_TRACE=adb,packets,rwx,usb,sync,sysdeps,transport,jdwp
# Ver comunicación USB
export ADB_TRACE=usb
adb devices
# Log a archivo
export ADB_TRACE=all
export ADB_TRACE_OUTPUT=/tmp/adb.log
adb devices
cat /tmp/adb.log
Análisis de Problemas de Conexión
#!/bin/bash
# diagnose_adb.sh
echo "🔍 Diagnóstico de ADB"
echo "===================="
# 1. Verificar servidor
echo -e "\n1. Estado del servidor:"
if pgrep -x "adb" > /dev/null; then
echo "✅ Servidor ADB corriendo"
echo " PID: $(pgrep -x adb)"
else
echo "❌ Servidor ADB no está corriendo"
fi
# 2. Verificar puerto
echo -e "\n2. Puerto 5037:"
if netstat -an | grep -q ":5037.*LISTEN"; then
echo "✅ Puerto 5037 en uso"
else
echo "❌ Puerto 5037 no está escuchando"
fi
# 3. Verificar USB
echo -e "\n3. Dispositivos USB:"
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
lsusb | grep -i "android\|google" || echo "No se detectan dispositivos Android"
elif [[ "$OSTYPE" == "darwin"* ]]; then
system_profiler SPUSBDataType | grep -i "android" || echo "No se detectan dispositivos Android"
fi
# 4. Verificar permisos
echo -e "\n4. Permisos:"
ls -la ~/.android/adbkey 2>/dev/null || echo "No se encuentra clave RSA"
# 5. Intentar conexión
echo -e "\n5. Intentando conexión:"
adb devices -l
🛡️ Seguridad en ADB
Mejores Prácticas
Desarrollo:
- Usar solo en redes confiables
- Deshabilitar ADB cuando no se use
- No usar adb root en producción
- Revisar claves autorizadas regularmente
Producción:
- ro.adb.secure=1 (ADB seguro)
- ro.debuggable=0 (No debuggeable)
- Deshabilitar ADB completamente
- USB debugging desactivado
WiFi ADB:
- Usar solo en red privada
- Cambiar puerto por defecto
- Firewall en el dispositivo
- VPN para conexiones remotas
Comandos de Seguridad
# Verificar modo seguro
$ adb shell getprop ro.adb.secure
1 # Seguro habilitado
# Ver build type
$ adb shell getprop ro.build.type
user # user, userdebug, o eng
# Verificar debuggeable
$ adb shell getprop ro.debuggable
0 # No debuggeable
# Revocar autorizaciones
$ adb shell rm /data/misc/adb/adb_keys # Requiere root
# Deshabilitar ADB
$ adb shell settings put global adb_enabled 0
🎯 Ejercicios Prácticos
Ejercicio 1: Explorar Arquitectura
# 1. Verificar componentes
ps aux | grep adb # Ver servidor
adb shell ps | grep adbd # Ver daemon
# 2. Analizar puerto
netstat -tulpn | grep 5037
# 3. Ver comunicación
export ADB_TRACE=packets
adb shell echo "test"
Ejercicio 2: Cambiar Modos de Conexión
# 1. USB → WiFi
adb tcpip 5555
adb connect [IP]:5555
# 2. WiFi → USB
adb usb
# 3. Puerto personalizado
adb tcpip 5556
adb connect [IP]:5556
Ejercicio 3: Debugging
# 1. Activar trace completo
export ADB_TRACE=all
export ADB_TRACE_OUTPUT=adb_debug.log
# 2. Ejecutar comando
adb devices
# 3. Analizar log
grep "transport" adb_debug.log
grep "usb" adb_debug.log
📚 Resumen
Has aprendido la arquitectura completa de ADB:
- ✅ Componentes cliente-servidor-daemon
- ✅ Protocolos de comunicación
- ✅ Autenticación RSA y seguridad
- ✅ Modos de conexión USB/WiFi/Ethernet
- ✅ Port forwarding y servicios
- ✅ Debugging y troubleshooting
🚀 Próximo Paso
Con el entendimiento de la arquitectura, ahora exploraremos los comandos esenciales de ADB.
👉 Continuar con Capítulo 3: Comandos Esenciales
Tip Pro: Entender la arquitectura de ADB te ayudará a diagnosticar problemas rápidamente. Cuando algo falle, piensa en qué componente puede estar fallando: ¿cliente, servidor o daemon?