refactor(android): split session JNI into modules, HUD-gated stats, AAudio open retry

- native: the 756-line session.rs becomes session/{mod,connect,input,planes}.rs
  around a SessionHandle (connect lifecycle + trust, input plane shims, plane
  start/stop + stats drain).
- Decode-stats sampling is HUD-gated (nativeSetVideoStatsEnabled): with the
  overlay hidden the decode thread skips the per-AU clock read + lock; enabling
  resets the measurement window.
- audio: the AAudio open path is a per-sharing-mode try_open closure — the
  realtime callback state (ring, prime, free-list) is rebuilt per attempt, so a
  failed exclusive-mode try can't leak state into the shared-mode retry.
- Kotlin: ConnectScreen/StreamScreen slimmed by extracting ConnectDialogs,
  StatsOverlay and TouchInput.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 11:04:43 +02:00
parent 3678c182d5
commit bd4e15b68d
18 changed files with 1922 additions and 1532 deletions
@@ -114,6 +114,14 @@ object NativeBridge {
*/
external fun nativeVideoStats(handle: Long): DoubleArray?
/**
* Gate per-frame stats sampling on the HUD being visible: while disabled the decode thread
* skips the per-AU clock read + lock, so toggle this with the overlay (and only poll
* [nativeVideoStats] while it's on). Enabling resets the measurement window — no stale data.
* Sticky for the session (survives video stop/start). No-op on `0`.
*/
external fun nativeSetVideoStatsEnabled(handle: Long, enabled: Boolean)
/**
* Start host→client audio: Opus decode → jitter ring → AAudio (LowLatency), all in Rust. No-op
* if already started. Best-effort — a failure leaves video streaming.