Kiosk Operations Runbook (Android Device Owner)
Operator-facing procedures for provisioning, recovering, updating, Wi-Fi, and decommissioning osd kiosk tablets. Any team member can follow these without the original developer present.
osd runs as an Android Device Owner kiosk: the tablet is locked into osd (lock-task), osd is the home launcher, and reboots return to osd. The only way to remove Device Owner is a factory reset — there is no "uninstall".
Target devices: Redmi Pad 2 Pro (HyperOS, primary), Lenovo Tab M11 / Samsung Tab A9+ (fallback).
PIN reference (know which PIN does what)
| PIN | Purpose | Set where | Default |
|---|---|---|---|
Shift-PIN |
Front door → connects the tablet to a specific Dienst |
Admin panel, per event (Story 9.14), synced to the tablet |
none — admin chooses 6 digits |
Firmen-PIN (company) |
"Neuen Dienst anlegen" offline when no Dienst is synced |
Front door or Settings → Firmen-PIN (Story 9.10) |
none — first entry sets it (set-on-first-use), same as the Wartungs-PIN |
Wartungs-/Admin-PIN |
Maintenance escape hatch + gated Settings (enrollment, device settings, lock-screen text, restart, update policy) |
Set-on-first-use in the maintenance overlay |
none — first entry sets it |
The maintenance escape hatch: 10 quick taps on the version label in Settings (only on a provisioned Device-Owner tablet) open the Wartungs-PIN dialog → a small launcher (Settings / Files / Camera / Notes / Maps) — the only way to reach Android Settings or files from inside the locked kiosk. It auto-relocks after ~5 min, on exit, or on reboot. (This replaces the earlier hidden top-right long-press gesture.)
Procedure 1 — Provision a new tablet
Preconditions (do these first):
-
Set the tablet’s Android system locale to Deutsch (Deutschland) before the factory reset — the setup-wizard text and the expected-output below are German, and a mismatched locale causes needless troubleshooting. (osd’s provisioning also sets
PROVISIONING_LOCALE/TIME_ZONE, but the wizard runs before that.) -
Have the latest
provision.pngfrom the GitLab release open on a second device (phone/laptop screen) ready to show the tablet camera. Download it from the release’s package URL (API form, anon-reachable):https://gitlab.com/api/v4/projects/70262263/packages/generic/releases/<version>/provision.png -
A field-event Wi-Fi or phone hotspot the tablet can join (the wizard downloads the ~143 MB APK over it).
Steps (QR path — preferred):
-
Factory reset the tablet (Settings → System → Reset, or Recovery). On HyperOS the recovery menu may be Chinese — use a translate-camera app.
-
On the welcome screen, do NOT sign in. Tap the screen 6× on the same spot → the QR-provisioning flow opens.
-
Connect to Wi-Fi when prompted.
-
Enable the camera if asked, then scan
provision.png. -
The wizard shows „Dieses Gerät gehört Ihrer Organisation" ("owned by business"), downloads + installs osd, runs the provisioning handshake, and boots into the osd kiosk. Expect ≤ 5 min on 50 Mbps.
-
Expected end state: the osd logo screen with „Einsatzbereitschaft herstellen" + a Settings gear. No Android home, no app drawer.
-
-
Enrol the device: Settings (gear → Wartungs-PIN, set it now on first use) → Geräte-Einschreibung → enter the enrollment token + device name → confirm the GPG fingerprint against the org key holder (Epic 4 trust anchor). This binds the device + GPG trust.
Steps (adb path — fallback, when the QR flow won’t take): Works only on an un-provisioned tablet (once provisioned, USB adb stays unauthorized and Wireless debugging can’t pair — see Procedure 2 / the adb-on-kiosk limitation). On a fresh factory-reset tablet:
-
Skip all accounts in the wizard.
-
Settings → enable Developer options → USB-Debugging.
-
adb install -r app-universal-release.apk -
adb shell dpm set-device-owner de.eventsanitaeter.es_dashboard/.OsdDeviceAdminReceiver -
Reboot → osd kiosk. Then enrol as in step 6 above.
Failure mode — "boots into kiosk but enrolment fails" (bricked-but-locked): server unreachable, enrollment token exhausted, or the GPG fingerprint dialog was dismissed → the tablet is now locked into osd without enrolment and cannot sync or document for a real Dienst. **Only recovery is Procedure 2 (factory reset
-
reprovision).** Fix the root cause first (server reachable? fresh token? right fingerprint?) before reprovisioning.
Procedure 2 — Recover a stuck tablet
Match the symptom → remediation:
| Symptom | Remediation |
|---|---|
Black screen / frozen |
Physical power-button long-press 8—12 s → force-reboot → reboot loads osd. |
Android home screen instead of osd |
Device Owner was lost → factory reset + reprovision (Procedure 1). |
osd crash-loops ("ES Dashboard keeps stopping") |
Global Actions (power long-press) → power off → power on. If it still loops after 2 reboots → factory reset + reprovision. Known cause: a device provisioned from v0.10.17/v0.10.18 has a buggy OTA watcher (self-reinstall loop) — do not provision from those tags; use v0.10.19 or later. If reachable, clearing osd’s cache (not data) removes the cached APK and breaks the loop while keeping enrolment. |
"Kiosk degraded" banner in Settings (Story 9.2 |
Device Owner lost (e.g. HyperOS OS update). Read the crash log in Settings for diagnostics → factory reset + reprovision. |
Sync indicator shows pending ops AND the tablet must be reset |
Operator decision: accept data loss and reset (factory reset wipes the op-queue) or wait for sync to drain if the tablet is still partly usable. If the device is too broken to even reach the sync indicator, accept the loss and proceed. |
Forgotten Firmen-/Wartungs-PIN, locked out |
The Wartungs-PIN gates the escape hatch; if forgotten, the maintenance gesture can still be triggered but not satisfied → recovery is factory reset + reprovision. |
adb-on-kiosk limitation: on a provisioned HyperOS tablet, USB adb stays unauthorized (the auth dialog is suppressed under lock-task) and Wireless debugging pairing fails. So adb is not a recovery tool on a live kiosk — the in-app ADB-enable verb (Settings, Story 9.7) is the only way to turn adb on, and OTA is the only reliable way to land a new build. Plan recovery around factory reset + reprovision, not adb.
Factory-reset data loss: a factory reset destroys all local osd data — open protocols, locally-created (offline) Dienste, and queued op_log entries. When the tablet is reachable, verify the sync indicator shows "no pending ops" before resetting. When it is not reachable, accept the loss and proceed.
Recovery-time target: ≤ 20 min to back in the field on representative event Wi-Fi (50 Mbps). This is a target, not a commitment (the earlier 15-min figure was optimistic).
Procedure 3 — Update osd across the fleet
Primary path — in-app OTA (no factory reset):
-
Settings → „Nach Updates suchen". osd checks the stable
latest.json, downloads the new APK, and silently installs it via Device-Owner self-install (kiosk_install_apk) — works inside the kiosk, no operator tap needed beyond starting it. The device relaunches once into the new version. -
Cut a release by tagging
vX.Y.Z(CI publishes the APK + updates the stablelatest.json); devices pick it up on the next check.
OTA bootstrap reality: the OTA-endpoint fix lives in the binary, so a device on a pre-fix build can’t OTA to the fix — the first device with the fix must be sideloaded once, then it can OTA onward. Never provision/keep devices on v0.10.17/v0.10.18 (broken OTA watcher); v0.10.19+ is safe.
Fallback path — if OTA fails (signature mismatch, downgrade attempt, disk full): re-trigger from Settings; if still failing, sideload the APK via the adb path on a reset device (Procedure 1), or escalate to Procedure 5. There is no factory-reset-as-update cost in the normal path.
System (Android OS) updates are separate: Settings → Gerät → System-Updates (Story 9.11) sets the policy (Aufschieben / Zeitfenster / Automatisch). A freshly-provisioned kiosk defaults to Aufschieben (postpone, ≤ 30 days) so an OS update never reboots a tablet mid-shift. (Whether HyperOS honours the policy is still being verified on-device.)
Procedure 4 — Change Wi-Fi mid-event
A Sanitäter opens osd Settings → WLAN (Story 9.5), scans available networks, and joins — no operator escort, no kiosk exit. If the WLAN section is unavailable (Device Owner lost), Procedure 2 applies.
Status: the in-app WLAN section is Story 9.5 (not yet shipped). Until it lands, set Wi-Fi during provisioning (Procedure 1 step 3), or reach Android Wi-Fi settings via the maintenance escape hatch (10 taps on the version label in Settings → Wartungs-PIN → Settings).
Procedure 5 — Decommission / fleet-wide QR reissue
Decommission a tablet:
-
Admin side: revoke the device in the admin panel (Epic 5 — device off-boarding).
-
Tablet side: factory reset — the only way to remove Device Owner (the DPC cannot be uninstalled while provisioned).
Fleet-wide reissue (keystore rotation): when the production signing keystore is rotated (Story 7.1, or any future rotation), every previously-printed QR becomes stale — the QR encodes the signing-cert checksum. All tablets must be reprovisioned with the new provision.png. Fleet-wide impact; schedule during a downtime window.
See also
-
Release / branch state + decisions:
docs/superpowers/plans/RELEASE-PLAN.md(in-repo; not published to the portal) -
Architecture:
_bmad-output/planning-artifacts/architecture.md(Addendum: Android Kiosk Deployment) -
Onboarding (first login + enrolment):
docs/ONBOARDING.md— Story 7.4, not yet written; it will reference this runbook for the provisioning prerequisite.