- Replace raw FFI with proper `jni` crate for string marshalling - Wire QUIC transport in engine: connect to relay, crypto handshake (CallOffer/CallAnswer, X25519+Ed25519), send/recv MediaPackets - Feed received packets into jitter buffer (was previously ignored) - Add connect screen UI with CALL button (idle state) and in-call controls (mute, speaker, hang up, live stats) - Hardcode relay 172.16.81.125:4433, room "android" - Add comprehensive docs in docs/android/: architecture.md (8 mermaid diagrams), build-guide.md, debugging.md, maintenance.md, roadmap.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.9 KiB
4.9 KiB
Roadmap & Known Gaps
Current State Summary
The Android client can connect to a WZP relay, complete the crypto handshake, and exchange audio in real-time. Two phones on the same network can talk to each other through the relay.
What Works (April 2025)
- QUIC transport to relay with room-based SFU
- Full crypto handshake (X25519 ephemeral + Ed25519 signatures)
- Opus 24kbps encoding/decoding at 48kHz
- Lock-free audio I/O via Oboe (capture + playout)
- AEC (acoustic echo cancellation) with 100ms tail
- AGC (automatic gain control)
- RaptorQ FEC encoder/decoder (wired to pipeline)
- Adaptive jitter buffer (10-250 packets)
- UI with connect/disconnect, mute, speaker, live stats
- Random identity seed per app launch
Known Gaps
P0 — Must fix for usable calls
| Gap | Impact | Where to fix |
|---|---|---|
| Media encryption not applied | Audio sent in cleartext over QUIC | engine.rs — pass _session to send/recv, encrypt/decrypt payloads |
| FEC repair symbols not sent | No loss recovery — audio gaps on packet loss | engine.rs send task — call fec_encoder.generate_repair() and send repair packets |
| Quality reports not sent | Relay can't monitor quality, no adaptive switching | engine.rs — periodically attach QualityReport to MediaPacket header |
| CallService not started | Call dies when app is backgrounded | CallViewModel.startCall() — call CallService.start(context) |
P1 — Important for production
| Gap | Impact | Where to fix |
|---|---|---|
| Hardcoded relay address | Can't change server without rebuild | Add settings screen with SharedPreferences |
| No reconnection logic | Connection drop = call over | engine.rs network task — detect disconnect, retry with backoff |
| No adaptive quality switching | Stays on GOOD profile even in bad conditions | Wire AdaptiveQualityController to network path quality from QuinnTransport |
| Identity seed not persisted | New identity every launch | Save seed to Android Keystore or SharedPreferences |
| No Bluetooth audio routing | AudioRouteManager exists but not wired to UI |
Add Bluetooth button to InCallScreen, call AudioRouteManager methods |
| No ringtone/notification for incoming | Only outgoing calls supported | Need signaling for call setup (currently both sides initiate independently) |
P2 — Nice to have
| Gap | Impact | Where to fix |
|---|---|---|
| No android_logger | Rust tracing output lost on Android | Add android_logger crate, init in nativeInit() |
| Stats don't include network metrics | Loss/RTT/jitter always 0 | Feed QuinnTransport.path_quality() back to stats |
| No ProGuard/R8 minification | Release APK larger than necessary | Enable isMinifyEnabled = true in build.gradle.kts |
| Single ABI (arm64-v8a) | No support for older 32-bit devices or emulators | Add armeabi-v7a and x86_64 to cargo-ndk build |
| No call history | Can't see past calls | Add Room database for call log |
| No contact integration | Manual relay/room entry | Add contacts with fingerprint-based identity |
Architecture Evolution Plan
Phase 1: Make Calls Reliable (current → next)
[x] QUIC connection to relay
[x] Crypto handshake
[x] Audio encode/decode pipeline
[ ] Media encryption (ChaCha20-Poly1305)
[ ] FEC repair packet transmission
[ ] Foreground service for background calls
[ ] Reconnection on network change
Phase 2: Quality & Polish
[ ] Adaptive quality (GOOD → DEGRADED → CATASTROPHIC switching)
[ ] Quality reports in MediaPacket headers
[ ] Network path quality display (real RTT, loss, jitter)
[ ] Settings screen (relay, room, seed persistence)
[ ] Bluetooth/wired headset audio routing
[ ] Rust android_logger for debugging
Phase 3: Production Features
[ ] featherChat authentication
[ ] Persistent identity (Android Keystore)
[ ] Push notifications for incoming calls
[ ] Multi-party rooms (already supported by relay)
[ ] Call transfer
[ ] End-to-end encryption (bypass relay decryption)
Dependency Upgrade Path
quinn 0.11 → 0.12 (when released)
Quinn 0.12 will likely require rustls 0.24. Update both together:
Cargo.toml: bump quinn and rustls versions- Check
client_config()andserver_config()in wzp-transport for API changes - DATAGRAM API may change — check
send_datagram()/read_datagram()
Compose BOM 2024.01 → 2025.x
The LinearProgressIndicator progress parameter changed from Float to () -> Float in Material3 1.2+. If upgrading the BOM:
// Old (current):
LinearProgressIndicator(progress = level, ...)
// New (Material3 1.2+):
LinearProgressIndicator(progress = { level }, ...)
Kotlin 1.9 → 2.x
Kotlin 2.0 changed the Compose compiler plugin. Update kotlinCompilerExtensionVersion in composeOptions and the Kotlin Gradle plugin version together.