No description
  • Kotlin 69.6%
  • Shell 20.3%
  • JavaScript 7.5%
  • PowerShell 1.5%
  • AIDL 0.5%
  • Other 0.4%
Find a file
Massimiliano Santolo 9591c59353 feat(field-installer): blocca la MainActivity in portrait
L'app ruotava in landscape rovinando il layout (card/log a tutta larghezza).
android:screenOrientation=portrait, configChanges gia' gestiva orientation.
2026-10-16 15:47:02 +02:00
app fix(player): logo loading a 520dp + rimossa progress bar (no flicker al boot) 2026-10-16 15:16:52 +02:00
docs fix(field-installer): reclaim DS04 abilita a11y e mette il consent sul launcher 2026-10-16 15:16:52 +02:00
field-installer feat(field-installer): blocca la MainActivity in portrait 2026-10-16 15:47:02 +02:00
gradle/wrapper Initial commit: KipangaPlayer Android signage player 2026-05-01 06:59:30 +02:00
launcher fix(launcher): DEFAULT_PATH nel dropbear — shell SSH interattiva usabile 2026-10-16 15:43:42 +02:00
protocol player: flavor gecko (GeckoView bundled) per box con WebView obsoleta 2026-06-12 09:34:12 +02:00
tools fix(launcher): DEFAULT_PATH nel dropbear — shell SSH interattiva usabile 2026-10-16 15:43:42 +02:00
.gitignore chore: gitignora tools/kipanga-release.sh (contiene RELEASE_PUBLISH_TOKEN) 2026-07-07 11:14:52 +02:00
build.gradle.kts Remote stack: outbound reverse SSH tunnel to pop.pointonpeople.com 2026-05-13 10:30:21 +02:00
gradle.properties Initial commit: KipangaPlayer Android signage player 2026-05-01 06:59:30 +02:00
gradlew Initial commit: KipangaPlayer Android signage player 2026-05-01 06:59:30 +02:00
gradlew.bat Initial commit: KipangaPlayer Android signage player 2026-05-01 06:59:30 +02:00
README.md chore(field-installer): embedda il player 1.1.38, installer 1.1.1 2026-09-30 11:10:19 +02:00
settings.gradle.kts feat(field-installer): modulo app da campo buildabile (ex tools/phone-installer) 2026-07-03 11:45:15 +02:00

Kipanga Player (Android)

Stack di digital signage Android per totem unattended. Due APK co-firmate:

  • cloud.kipanga.player — renderizza la playlist del cliente (template HTML + JS sopra una WebView, ExoPlayer nativo per i video spot-creator), polla node.kipanga.cloud per la config, scarica gli asset gallery, manda heartbeat.
  • cloud.kipanga.launcher — Device Owner (o soft-kiosk dove il DO non è possibile). Fa da HOME di sistema, detiene le policy kiosk (Lock Task whitelist, status bar / keyguard disabled, stay-on-while-plugged-in), gira un watchdog che si appaia via AIDL col player e lo force-restart se hung, fa silent OTA install della APK player, e ospita lo stack di accesso remoto (Dropbear SSH su :2222, reverse tunnel, screenshot).

Più un modulo installer di supporto:

  • cloud.kipanga.installer (field-installer/) — app Android per il tecnico (telefono dedicato) che porta un adb statico bundlato e installa/provisiona la flotta senza Mac né root. Mirror on-device di tools/kipanga-fleet-installer.sh.

Versioni correnti: player 1.1.35 (code 38), launcher 1.1.10 (code 13), field-installer 1.1.1 (code 4); contratto AIDL ProtocolVersion.CURRENT = 3.

Le APK sono stabili e kiosk-locked. Bench box di validazione: T982 (Amlogic S905, Android 11), DS04 (Dahua RK3288, Android 8.1), Navori StiX (S922X). Target produzione: Android 11+ / API 30+.


Documentazione

Documento Per chi Cosa contiene
docs/dev/ONBOARDING.md sviluppatori ambiente, struttura moduli, build, test, convenzioni
docs/dev/ARCHITECTURE.md sviluppatori forma a runtime, contratto AIDL, schema state.json, failure mode
docs/dev/COMPATIBILITY.md sviluppatori matrice di compatibilità launcher↔player↔AIDL proto
docs/dev/PROVISIONING.md sviluppatori / tecnici modello a 3 classi HW (Clean-DO / Reclaim / Soft-kiosk), engine kipanga-provision.sh
docs/ops/PREPARAZIONE_PERIFERICA.md tecnici onsite prerequisiti/prima messa a punto per modello (compatibilità, no account, ADB, quirk)
docs/ops/INSTALLAZIONE.md tecnici onsite provisioning presso il cliente — percorso cavo USB / WiFi
docs/ops/COMANDI_SSH.md supporto / tecnici cheat-sheet comandi operativi via SSH (reboot, refresh, log, stato, screenshot)
docs/ops/ACCESSO_REMOTO.md supporto SSH, reverse tunnel, screenshot
docs/ops/OTA_SAFE_PROCEDURE.md rilascio / supporto procedura OTA sicura: preflight statico, canary bench, soak, batch rollout
docs/ops/TROUBLESHOOTING.md supporto / tecnici diagnosi e recupero device, factory reset
docs/ops/COMBO_TELECOMANDO.md tecnici gesture hardware (hold WiFi / hold factory-reset)
field-installer/README.md sviluppatori / tecnici app installer Android (adb bundlato), architettura e uso
docs/team-server/ team server Kipanga API OTA / provisioning, problemi di data-quality

Stato

Area Stato
Robustezza player (state.json, tolerant config parser, WebView watchdog, log rotator, SC retry+refresh, restart-on-do-refresh) ✅ done
Launcher + modulo AIDL :protocol + watchdog ✅ done
Device Owner + Lock Task + kiosk UI policies ✅ done
Tooling provisioning (kipanga-install.sh, kipanga-provision.sh, kipanga-fleet-installer.sh, field-installer, QR template) ✅ done
SSH interattivo su Android (fix Dropbear getpwnam/segfault, sessioni PTY/console) ✅ done — validato su T982 + StiX
OTA: silent player install via AIDL launcher ✅ done client-side — endpoint server pendenti, vedi docs/team-server/API_OTA_PROVISIONING.md
SSH server locale (Dropbear cross-compilato, patch Android-compat) ✅ done
Reverse SSH tunnel outbound device→pop.pointonpeople.com ✅ done — validato end-to-end
Screenshot remoto via MediaProjection + endpoint HTTP ✅ done (consent auto-tappato, zero operator interaction)
authorized_keys fleet-wide sync (ETag, atomic write) ✅ done
Controllo remoto interattivo — stream MJPEG + iniezione tap/swipe via HTTP ✅ done client-side — da testare su HW reale

Stack tecnologico

Layer Scelta
Linguaggio Kotlin 2.2.21
Build Gradle 9.4.1 (wrapper) + AGP 9.2.0
JVM toolchain 21
Min / target SDK 28 / 34
HTTP (player) OkHttp 4.12
HTTP (launcher) java.net.HttpURLConnection (solo stdlib — dex piccola)
JSON Gson 2.10.1 + TolerantConfigParser custom
Async Kotlinx Coroutines 1.7.3
WebView WebView di sistema (Chromium, warm-up al boot)
Video nativo androidx.media3 / ExoPlayer 1.3.1
IPC AIDL — ILauncherWatchdog nel modulo :protocol
Test JUnit 4 + kotlin-test, unit JVM (:app:testDebugUnitTest)

Layout repo

KipangaPlayer/
├── app/            :app            — cloud.kipanga.player
├── launcher/       :launcher       — cloud.kipanga.launcher (Device Owner / soft-kiosk)
│   └── src/main/jniLibs/<abi>/libdropbear.so   — SSH server cross-compiled (committato)
├── field-installer/:field-installer — cloud.kipanga.installer (app installer, adb bundlato)
├── protocol/       :protocol       — Android library, solo contratto AIDL
├── tools/
│   ├── kipanga-install.sh          — provisioning onsite one-script (scan+install+DO)
│   ├── kipanga-provision.sh        — engine provisioning a 3 classi HW
│   ├── kipanga-fleet-installer.sh  — engine di riferimento del field-installer
│   ├── ota-preflight.sh            — gate statico OTA (firma + manifest + versionCode)
│   ├── ota-canary-watch.sh         — soak automatico del canary
│   ├── install_tunnel_key.sh       — converte + installa la chiave del reverse tunnel
│   ├── build-dropbear.sh           — cross-compile del server SSH (con patch Android)
│   ├── qr_provisioning_template.json — template QR factory-reset
│   └── … (provision-dahua-ys.sh, dahua-ds04-webview.sh, kipanga-release.sh, …)
├── docs/                   — vedi sezione Documentazione sopra
└── README.md

Build rapida

# Debug, entrambe le APK
./gradlew :app:assembleDebug :launcher:assembleDebug

# Release firmate (keystore in ~/.kipanga-secrets/keystore.properties)
./gradlew :app:assembleRelease :launcher:assembleRelease

# Unit test del player
./gradlew :app:testDebugUnitTest

# Provisioning onsite (scan rete + install launcher/player + Device Owner)
tools/kipanga-install.sh

Setup completo, struttura dei moduli e convenzioni → docs/dev/ONBOARDING.md.


Pipeline a runtime (in breve)

Boot → MainActivity launcher → DO policies applied → player lanciato → config pollata da node.kipanga.cloud → registration se status_code ∈ {0,5} → gallery sync → page render → metronome rotation. Watchdog AIDL ogni 10 s; se silenzio > 30 s il launcher force-restart il player. Flag dal server: do_refresh=1 (restart pulito), do_upgrade=1 (re-fetch template firmware), do_apk_upgrade=1 (silent self-update).

Quadro completo → docs/dev/ARCHITECTURE.md.