Files
fn_registry/bash/functions/infra/android_emulator_start.sh
T
egutierrez efc9911925 feat(kotlin-compose): design system fn.compose:ui + toolbelt android Linux-first
Design system Compose (kotlin/functions/ui, modulo Gradle `fn.compose:ui`):
- FnTokens + FnTheme con la paleta heredada al hex de cpp/DESIGN_SYSTEM.md
  (Mantine v9 dark + indigo), identica a la web @fn_library y a las apps C++.
- 26 componentes Compose (Layout/Display/Inputs/Feedback/Data/Charts) +
  FnTheme + FnTokens registrados en el registry (28 entradas kind=component
  lang=kt domain=ui), descubribles via fn_search. Habilitan init_kotlin_app.

Recuperacion: el commit cb6d9e6 habia anadido `kotlin/functions/ui/` al
.gitignore, por eso el design system nunca se versiono y se perdio del working
tree. Des-ignorado; el .gitignore interno del modulo ya excluye
build/.gradle/local.properties. La gallery (apps/gallery_kt) se recupero del
sub-repo Gitea y sus 27 componentes se reconstruyeron con su MainActivity como
contrato exacto.

Toolbelt Android Linux-first (antes asumia WSL2 + Windows):
- adb_wsl 1.1.0, android_emulator_start 1.1.0, android_emulator_list 1.1.0:
  resuelven adb/emulator nativos del SDK ($ANDROID_HOME), .exe solo fallback WSL2.
- android_emulator_start: fix `timeout adb_run wait-for-device` (timeout no puede
  ejecutar una funcion del shell; ahora invoca el binario $ADB directamente).
- install_android_sdk 1.0.1: fix licencias bajo pipefail (SIGPIPE de `yes`) +
  trap EXIT con variable unbound.
- docs/capabilities/android.md regenerado Linux-first + seccion design system.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 23:43:59 +02:00

126 lines
5.0 KiB
Bash

#!/usr/bin/env bash
# android_emulator_start — Arranca un AVD en background y espera a que bootee.
# Uso: android_emulator_start <avd_name> [timeout_s]
set -euo pipefail
# ---------------------------------------------------------------------------
# Source adb_wsl si está disponible (provee ADB, adb_run, adb_wait_boot)
# ---------------------------------------------------------------------------
_ADB_WSL_SH="$(dirname "${BASH_SOURCE[0]}")/adb_wsl.sh"
if [[ -f "$_ADB_WSL_SH" ]]; then
# shellcheck source=adb_wsl.sh
source "$_ADB_WSL_SH"
else
# Fallback inline: resolver ADB (Linux-first; WSL fallback)
if [[ -z "${ADB:-}" ]]; then
_sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
if [[ -n "$_sdk" && -x "$_sdk/platform-tools/adb" ]]; then
ADB="$_sdk/platform-tools/adb"
elif command -v adb &>/dev/null; then
ADB="$(command -v adb)"
else
ADB="${ANDROID_SDK_WIN:-/mnt/c/Users/$USER/AppData/Local/Android/Sdk}/platform-tools/adb.exe"
fi
unset _sdk
fi
adb_run() { "$ADB" "$@"; }
adb_wait_boot() {
local timeout_s="${1:-120}"
local elapsed=0 interval=3 val
while (( elapsed < timeout_s )); do
val=$(adb_run shell getprop sys.boot_completed 2>/dev/null | tr -d '[:space:]')
[[ "$val" == "1" ]] && return 0
sleep "$interval"
(( elapsed += interval ))
done
echo "android_emulator_start: timeout ${timeout_s}s esperando boot." >&2
return 1
}
fi
# ---------------------------------------------------------------------------
# Resolver EMULATOR (Linux-first; WSL fallback)
# ---------------------------------------------------------------------------
if [[ -z "${EMULATOR:-}" ]]; then
_sdk="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
if [[ -n "$_sdk" && -x "$_sdk/emulator/emulator" ]]; then
EMULATOR="$_sdk/emulator/emulator"
elif command -v emulator &>/dev/null; then
EMULATOR="$(command -v emulator)"
elif grep -qiE "(microsoft|wsl)" /proc/version 2>/dev/null; then
EMULATOR="${ANDROID_SDK_WIN:-/mnt/c/Users/$USER/AppData/Local/Android/Sdk}/emulator/emulator.exe"
fi
unset _sdk
fi
# ---------------------------------------------------------------------------
# android_emulator_start <avd_name> [timeout_s]
# ---------------------------------------------------------------------------
android_emulator_start() {
local AVD="${1:?android_emulator_start requiere el nombre del AVD como primer argumento}"
local timeout_s="${2:-180}"
# Validaciones de entorno
if [[ -z "${EMULATOR:-}" ]] || ! command -v "$EMULATOR" &>/dev/null; then
echo "android_emulator_start: emulator no encontrado. Instala el SDK + paquete 'emulator', exporta ANDROID_HOME, o fija EMULATOR=." >&2
return 1
fi
if [[ -z "${ADB:-}" ]] || ! command -v "$ADB" &>/dev/null; then
echo "android_emulator_start: adb no encontrado. Instala platform-tools, exporta ANDROID_HOME, o fija ADB=." >&2
return 1
fi
# Idempotencia: si ya hay un emulador corriendo, salir sin lanzar otro
if adb_run devices 2>/dev/null | grep -q "emulator-"; then
echo "already running"
# Imprimir el serial existente
adb_run devices 2>/dev/null | grep "emulator-" | awk '{print $1}' | head -n1
return 0
fi
local log_file="/tmp/emulator_${AVD}.log"
local pid_file="/tmp/emulator_${AVD}.pid"
# Lanzar emulador en background
"$EMULATOR" -avd "$AVD" -no-boot-anim -no-snapshot-load >"$log_file" 2>&1 &
local emu_pid=$!
echo "$emu_pid" > "$pid_file"
# Esperar a que el dispositivo aparezca en adb.
# Usamos el binario "$ADB" directamente (no la funcion adb_run): `timeout`
# ejecuta un comando externo y no puede ver funciones del shell, asi que
# `timeout ... adb_run` fallaba siempre con "command not found".
local wait_timeout=$(( timeout_s / 2 ))
if ! timeout "$wait_timeout" "$ADB" wait-for-device 2>/dev/null; then
echo "android_emulator_start: timeout esperando que el dispositivo aparezca en adb (${wait_timeout}s)." >&2
return 1
fi
# Verificar que el proceso del emulador sigue vivo
if ! kill -0 "$emu_pid" 2>/dev/null; then
echo "android_emulator_start: el proceso del emulador (PID $emu_pid) murió antes de completar el boot." >&2
echo " Log: $log_file" >&2
return 1
fi
# Esperar boot completo (sys.boot_completed=1)
local boot_timeout=$(( timeout_s - wait_timeout ))
if ! adb_wait_boot "$boot_timeout"; then
echo "android_emulator_start: timeout ${timeout_s}s esperando boot completo del AVD '$AVD'." >&2
echo " Log: $log_file" >&2
return 1
fi
# Obtener serial del dispositivo emulado
local serial
serial=$(adb_run devices 2>/dev/null | grep "emulator-" | awk '{print $1}' | head -n1)
echo "$serial"
return 0
}
# Ejecutar si se invoca directamente (no sourceado)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
android_emulator_start "$@"
fi