docs: document the Android receiver app (Phase 8)
README: phone-as-second-screen section (build, install, sender usage, multi-monitor caveat). RUNBOOK: Android build/test procedure, device-test commands, and the API-36 platform quirks found during validation. PHASES: Phase 8 milestones, all validated. MEMORY: current phase state and the hard-won Android/portal lessons.
This commit is contained in:
+25
-2
@@ -1,10 +1,33 @@
|
||||
# Project Memory — screen_cast
|
||||
|
||||
Last updated: Phase 6 (discovery + signaling) complete and validated over
|
||||
loopback; current phase is Phase 7.
|
||||
Last updated: Phase 8 (Android receiver app) complete and validated on a
|
||||
Fairphone 6; all prior phases done.
|
||||
|
||||
## Project state
|
||||
|
||||
- **Phase 8 done: Android receiver app** (`android/`, Kotlin, minSdk 30,
|
||||
app id `screen_cast.receiver`): phone as second receiver (screen → HDMI via
|
||||
USB-C DP-alt-mode). Speaks the existing signaling+RTP protocol — no C++
|
||||
changes. AGP 9 **built-in Kotlin** (no kotlin plugin, no `kotlinOptions`;
|
||||
Kotlin targets `compileOptions`, Java 17); no androidx (framework +
|
||||
org.json + JUnit). 25 JVM tests green. Validated end-to-end on a
|
||||
Fairphone 6 (API 36): offer/answer → MediaCodec → fullscreen letterboxed
|
||||
render; PLI recovery on real Wi-Fi loss. Hard-won API-36 quirks (in
|
||||
RUNBOOK): `INTERNET` permission is REQUIRED for NsdService;
|
||||
`DatagramSocket.localPort` (`.port` is -1 unconnected; `.localAddress` is
|
||||
Inet6Address, not InetSocketAddress); pass the Surface to
|
||||
`MediaCodec.configure()` + `start()`; render via
|
||||
`releaseOutputBuffer(render=true)`; C2 AVC needs a concrete size at
|
||||
configure (in-band SPS reconfigures); `MediaFormat.format()`/
|
||||
`KEY_MIME_TYPE` not public in API 36; NSD `RegistrationListener` replaced
|
||||
`ResolutionListener` (reflection fallback for older devices);
|
||||
**`android._video-scaling`: C2 scales output to the Surface** → letterbox
|
||||
by sizing the TextureView to the video aspect, NOT a transform matrix
|
||||
(double scale). Sender-side: Hyprland + GTK portal's `--target monitor`
|
||||
picks the FIRST output (eDP-1, wrong display) — use `--target window`
|
||||
(hyprland-share-picker). Activity FQN for `am start`:
|
||||
`screen_cast.receiver/screen_cast.ReceiverActivity` (Kotlin package =
|
||||
namespace `screen_cast`).
|
||||
- **Phase 6 done**: Avahi mDNS discovery (`_screencast._tcp` — receiver
|
||||
announces its signaling port via a threaded-poll Avahi client; senders
|
||||
browse+resolve) plus JSON session signaling (offer/answer) over TCP with
|
||||
|
||||
Reference in New Issue
Block a user