diff --git a/docs/MVP_PLAN.md b/docs/MVP_PLAN.md index 417f404..21d439a 100644 --- a/docs/MVP_PLAN.md +++ b/docs/MVP_PLAN.md @@ -110,13 +110,17 @@ make logcat a true push stream over `adb_shell` for MVP.** ### Why not pure logcat push (yet) -`adb_shell`'s `AdbDeviceTcpAsync.shell()` is **request → full-response**; there is no -incremental/streaming read API on the stable surface. Running `exec logcat` blocks -forever. A true stream means either hacking adb_shell internals (fragile across its -releases) or adding a dependency (violates constraints). Also, logcat does not -reliably carry *playback state* changes for third-party apps — it reliably carries -**foreground/app lifecycle** events (verified R8: `ActivityTaskManager: START u0 -{… cmp=/}` on every app open, including home-button → launcher). +CORRECTION (C-STREAM, spike-verified on our pinned range): `adb_shell` 0.4.4 +**does** ship `streaming_shell` — a generator yielding each line of output — on +both the sync `AdbDevice` and async `AdbDeviceAsync` (async needs the tiny +`aiofiles` + `async_timeout` extras, both already HA-ecosystem staples). So a +true logcat push stream needs neither internals hacks nor a new major +dependency. What keeps the hybrid design honest is *device behavior*, not the +library: logcat does not reliably carry *playback state* for third-party apps — +it reliably carries **foreground/app lifecycle** events (verified R8: +`ActivityTaskManager: START u0 {… cmp=/}` on every app open, +including home-button → launcher). Streaming stability over multi-hour +connections still needs a device spike before we make it the sole trigger. ### The hybrid design (target architecture) @@ -128,8 +132,10 @@ entry.runtime_data = ShieldConnectionManager ├─ transport B: ADB (adb_shell) — persistent socket, no re-handshake per command ├─ watchdog task: health ping + exponential backoff reconnect (5s→…→300s cap) ├─ trigger listener: foreground-change events - │ (logcat -d -T1 ActivityTaskManager delta snapshots ~2–5 s cadence; - │ Phase 3 option: internals streaming if adb_shell ever supports it) + ├─ trigger listener: foreground-change events + │ Phase 1: logcat delta snapshots ~2–5 s cadence (safe default) + │ Phase 2+: streaming_shell logcat stream on a dedicated connection + │ (library support verified on 0.4.4; pending device stability spike) ├─ on trigger → cheap `dumpsys activity activities` (mResumedActivity confirm) │ → if changed → `dumpsys media_session` fetch ├─ heartbeat: `dumpsys media_session` every ~15–30 s while awake (safety net) @@ -333,16 +339,23 @@ tests cover all ladder branches. Files: - Deep links — now cheap: `media_type: app/url` → protocol - `send_launch_app_command` (port of core pattern) + BrowseMedia app directory; + `send_launch_app_command` (port of core pattern; the client auto-prefixes + `market://launch?id=` for bare package ids — C-LAUNCH, verified in the client + source, so no extra branch for app-id vs URI) + BrowseMedia app directory; per-app `am start` extras via ADB only for apps the protocol can't launch - (data-driven map in const). + (data-driven map in const; discovery recipe via + `adb shell cmd package dump ` in RESEARCH_IDEAS.md). +- Channel keys: add `channel_up`/`channel_down` (proto keycodes 166/167 — + trivial, no UI needed) alongside the §7 digit path. - Options: apps name/icon map editor (core androidtv_remote pattern), digit delay, IME toggle, privacy scope; finish config entry migration if needed. - Zeroconf discovery (`_androidtvremote2._tcp`) — auto-fill host, update entry on IP change; `manifest.json` gains the `zeroconf` integration dependency. - `adb_command` service + diagnostics (port androidtv patterns). -- Optional: logcat streaming via adb_shell internals if verified stable (behind - an option flag); otherwise keep snapshot approach. +- Optional: streaming_shell logcat stream as the trigger source (library + support verified on adb-shell 0.4.4, spike at goal round 9; pending a + multi-hour device stability spike) behind an option flag; default stays + delta snapshots. - Trim: fold Current App sensor if StateStore covers it; drop `running_apps_from_sessions` legacy; remove transitional external-entity code.