# TV Owner — Break-Glass Runbook

> **TL;DR:** Emergency escape ladder for a device-owner kiosk TV. L1 = D-pad combo **UP DOWN UP DOWN OK UP DOWN** → PIN **000000** (the MENU×5 combo is retired) → main menu (v1.8.0) *Open WiFi/Settings · Reload · Advanced · Cancel*; risky items (Full Settings / Exit Kiosk / Remove Device Owner) sit behind **Advanced** (2nd PIN). The trusted in-app un-own (L4, `clearDeviceOwnerApp`) is now **wired into the escape menu since v1.7.0** — L1 → admin PIN → *Advanced* (2nd PIN) → **"Remove Device Owner"** → red 3rd-PIN wipe confirm — so a **release-signed** TV finally has a remote-only un-own path (`dpm remove-active-admin` still fails on it). Physical break-glass wipe in the appendix remains the last resort (it trips FRP). Keep this saved offline before ANY TV goes device-owner.

"Break-glass" = the emergency procedures to **regain control of a locked-down (device-owner) kiosk TV** when normal use fails — app won't load, black screen, need to service/return the TV, or re-provision it. Keep this printed/saved before any TV goes device-owner.

App package: `com.tripgzio.webapp` · Admin component: `com.tripgzio.webapp/com.gigglezen.tvlauncher.KioskDeviceAdminReceiver` · Admin PIN default: **000000**

---

## Escape ladder — least drastic first

| # | Method | How | When |
|---|--------|-----|------|
| **L1** | D-pad escape combo | Press **UP DOWN UP DOWN OK UP DOWN within 5 s** → PIN-gated overlay → enter admin PIN **000000** → **main menu (v1.8.0): *Open WiFi/Settings · Reload · Advanced · Cancel***. The risky items — **Open Full Settings · Exit Kiosk · Remove Device Owner** — now live behind **"Advanced"**, which requires a **second admin PIN**; "Remove Device Owner" then needs a **red third-PIN confirm** before it un-owns. "Open Full Settings" opens the full Android TV Settings tree (Network / Developer options / Apps) — but factory reset stays blocked while we are device-owner (un-own via "Remove Device Owner"). The v1.8.0 overlay is responsive (no on-device cropping/overscan) with a bright D-pad focus highlight + explicit focus chaining. (There is **no MENU-key combo** — that key is unhandled since v1.4.0.) | TV works, staff need out or need WiFi/Settings |
| **L2** | Auto safe-mode | *Automatic* — crash-loop / dead WebView drops to the Recovery screen (Retry / staff WiFi-Settings) and releases the lock | App is crash-looping / black |
| **L3** | ADB force-stop | `adb connect <tv-ip>:5555` → `adb shell am force-stop com.tripgzio.webapp` | Foreground temporarily stuck |
| **L4** | In-app decommission (remove owner) | PIN-gated **"Remove Device Owner (retire TV)"** action → calls `dpm.clearDeviceOwnerApp()` from inside Android (never recovery — avoids FRP). **WIRED into the escape menu since v1.7.0: L1 combo → admin PIN → *Advanced* (2nd PIN) → "Remove Device Owner" → red 3rd-PIN wipe confirm.** ADB `dpm remove-active-admin` does **NOT** work on a release-signed owner (`SecurityException`). | Retire / repurpose the TV |
| **L5** | Factory reset | Blocked from Settings while WE are device-owner ("Action not allowed"). Use the physical break-glass wipe (appendix) — always works | Last resort / lost remote |

L1 and L2 need nothing but the remote. L1 (D-pad combo) exits the kiosk *lock* so staff can use the TV — it does **not** remove ownership. Fully removing ownership is now **L4** — the in-app "Remove Device Owner" wired into the escape menu since v1.7.0 (L1 → admin PIN → *Advanced* 2nd PIN → red 3rd-PIN confirm). The physical break-glass wipe (**L5**) is the last resort if the remote-only path fails.

## Scenario → action
- **Black screen / flashing loop** → should auto-enter **L2** safe-mode. If not, **L1** (D-pad combo). If the remote is dead, **L3**.
- **App loads a wrong/blank page but TV is responsive** → **L1** to exit, fix the server, relaunch.
- **Returning / repurposing the TV** → **L4** (remove owner), then factory reset if handing it off.
- **Re-provision to a new build/config** → **L4**, then re-run the provisioning script.
- **Lost remote AND no network** → physical **L5** via the TV's hardware reset (model-specific).

## Forward: provision a TV as device-owner
Requires a **factory-fresh** TV (no Google account, no other device-owner — Android refuses to set an owner otherwise).
1. Factory reset the TV. On the welcome screen, **do NOT sign into a Google account**, just connect WiFi.
2. Laptop on the same WiFi: enable wireless ADB on the TV (Developer options → Wireless debugging), `adb connect <tv-ip>:5555`.
3. Run: `scripts/setup-kiosk-tv.ps1 -TvIp <tv-ip>` — installs the APK from `apps.tripgzio.com` (or `-ApkPath`), sets device-owner, disables the stock launcher, sets our app as Home, launches it.
4. **Test the escapes (L1 + L2) before the TV leaves your hands.**

> The provisioning + update + rollback commands live in **RUNGUIDE.md → "Provision a NEW TV"**; this runbook owns only the *recovery* half. Keep the two in sync.

## Pre-flight checklist (before going owner on any TV)
- [ ] ADB reaches the TV (`adb devices` shows it).
- [ ] L1 (D-pad combo → 000000) verified working.
- [ ] L2 (crash → safe-mode) verified.
- [ ] L4 (remove-owner) path understood — remote-only un-own is wired since v1.7.0 (L1 → admin PIN → *Advanced* 2nd PIN → "Remove Device Owner" → red 3rd-PIN confirm); physical wipe stays the fallback.
- [ ] This runbook saved offline + the admin PIN known to staff.

---

# Appendix — Recovering a TV locked by an OLD device-owner (real case)

**2026-06-30/07-01, Onida ONI41F (Amlogic, Android 14).** A test TV had an old app (`com.gigglezen.gzlauncher`) set as **Device Owner**. That single fact bricked normal recovery: Settings → Reset showed **"Action not allowed — contact your IT admin"**, the device-admin entry's **Deactivate** was greyed out, and the app couldn't be uninstalled. This is the trap our own app must never recreate (see the in-app decommission TODO above).

## What we tried, and what happened

| Method | Result | Why |
|---|---|---|
| Settings → Factory reset | ❌ Blocked | Device-owner present → "Action not allowed" |
| `adb dpm remove-active-admin` | ❌ Blocked | Owner is `testOnly=false` → `SecurityException` |
| `adb am broadcast MASTER_CLEAR` / `FACTORY_RESET` | ❌ No-op | Needs system permission; shell (uid 2000) can't; FRP-triggering anyway |
| Write `/cache/recovery/command` (auto-wipe) | ❌ Permission denied | Needs root; `adb root` denied |
| **Bluetooth remote** in recovery | ❌ Dead | Recovery doesn't load the Bluetooth stack |
| **IR** (remote or phone IR-blaster) | ❌ No response | This TV's IR receiver is absent/dead (remote is BT-only; verified by turning BT off → remote went fully dead despite its IR LED emitting) |
| USB **mouse** in recovery | ❌ Useless | Recovery has no pointer cursor |
| Amlogic USB-Burning-Tool / SD `aml_autoscript` reflash | ⚠️ Impractical | Bypasses everything at SoC level, BUT needs an exact ONI41F firmware `.img` that Onida doesn't publish; wrong image hard-bricks |
| **✅ Physical TV power button (hardware key) + USB keyboard** | **✅ WORKED** | See below |

## ✅ The method that worked — *Likith Teja G's idea*

The reveal gesture for the AOSP **"No command"** robot screen is *Power + Volume-Up* (or a long-press). The catch: the **remote's** power button only opens the soft "shutdown" menu — it is **not** the raw `KEY_POWER`. **Likith's insight: the physical power button on the TV chassis _is_ the real hardware key.** So:

1. `adb connect <tv-ip>:5555` then `adb reboot recovery` (gets to the "No command" robot — the BT remote is useless from here on).
2. Plug a **USB keyboard** into the TV (works in *this* TV's recovery — not guaranteed on all Amlogic units).
3. At "No command": **hold the physical TV power button** + tap the keyboard's **Up arrow** (or long-press the physical power button) → the hidden **text menu appears**.
4. Keyboard **arrows + Enter** → `Wipe data / factory reset` → `Yes` → `Reboot system now`.

That cleared the device-owner and reset the TV to factory.

**Exact PC commands** (PowerShell or cmd — adjust the IP):
```
"%LOCALAPPDATA%\Android\Sdk\platform-tools\adb.exe" connect <TV_IP>:5555
"%LOCALAPPDATA%\Android\Sdk\platform-tools\adb.exe" -s <TV_IP>:5555 reboot recovery
```
(Current field Onida = `<LAN_IP>` on the TP-Link `<LAN_IP>` network; IPs drift — read the TV's own **Settings → Network**.)
(In PowerShell, prefix each line with `& ` and use `$env:LOCALAPPDATA`.) `adb` only *gets you to* recovery — it cannot click "wipe"; do steps 2–4 on the TV with the keyboard + physical power button.

**NOTE:** this forced/recovery path is ONLY needed when a device-owner blocks the normal reset. Once no device-owner is present, plain **Settings → System → About → Reset → Factory data reset** works and is the right tool.

## ⚠️ Caveat — Factory Reset Protection (FRP)
A recovery wipe is an *untrusted* reset, so a Google-certified TV may demand the **previously-synced Google account** at first-boot setup. Have that account's credentials ready, or the TV stalls at the Google login wall. (Yet another reason our own decommission must be the *in-app, trusted* path — never recovery.)

## Don't repeat this on our own fleet
- Provision device-owner **only on factory-fresh TVs** (no account, no other owner).
- The in-app trusted decommission (`clearDeviceOwnerApp`) is now **exposed in the L1 escape menu since v1.7.0** — PIN-gated "Remove Device Owner (retire TV)" under *Advanced* (2nd PIN) with a red 3rd-PIN wipe confirm — so a release TV can be un-owned remotely; the physical wipe below is only the fallback.
- Don't blanket-block factory reset without that escape.

---

**Related:** [Architecture](../ARCHITECTURE.md) · [Run guide](../RUNGUIDE.md) · [TV-native backlog](../docs/TV-NATIVE-BACKLOG.md) · [TV + web app install guide](../docs/webApp-and-Tv-setup-guide.md) · [TV device compatibility](../docs/tv-device-compatibility.md) · [Two TV apps](../.brain/knowledge/two-tv-apps.md)
