fix(voice,ios): scope AVAudioSession VoiceChat to call lifetime (#33)
Adopt a call-scoped VoIP audio session lifecycle so other apps' audio is not stopped while Chanora is idle and the in-call session does not get clobbered by media-server resets unrelated to voice. AppDelegate.swift - Set .ambient + .mixWithOthers as the idle baseline so the app does not hold a VoiceChat session when no call is active. - Switch to .playAndRecord + .voiceChat + .mixWithOthers + .duckOthers on demand via the new chanora/ios_audio_session MethodChannel, and revert to .ambient on deactivate. - Gate the media-services-reset rebuild on voiceSessionActive so a stray reset during idle no longer reactivates VoiceChat. ios_audio_session_controller.dart (new) - Thin Dart wrapper around chanora/ios_audio_session with activate/ deactivate; no-op on non-iOS; swallows PlatformException to keep audio start/stop resilient to platform-side races. main.dart - Activate the iOS audio session on BridgeEvent_AudioStarted, deactivate on BridgeEvent_AudioStopped, fire-and-forget via unawaited(). ios_voice_unit.rs - Add the 10 local bindings required by the render-callback closure preamble (wav_recorder_for_render, render_recorder_active, render_ref_len, render_ref_accum, cb_count, last_num_frames, num_frames_changes, callbacks_with_audio, callbacks_with_silence) so the iOS target compiles cleanly with the new lifecycle wiring. Tests - 5 unit tests in test/services/ios_audio_session_controller_test.dart cover activate/deactivate on iOS, no-op on non-iOS, and graceful PlatformException handling. Docs - SRS SRS-110 expanded to cover the call-scoped lifecycle invariant. - SysDes mobile-voice row updated to reflect the MethodChannel and .ambient idle baseline. - implementation-status-2026-05-28 voiceChat row flipped to done. Verification - flutter analyze: No issues found (2.8s) - flutter test: 195 passed / 2 skipped / 0 failed - cargo build -p chanora_audio --target aarch64-apple-ios: clean - cargo build -p chanora_audio (macOS host): clean Device QA matrix (Spotify-keeps-playing-while-idle, mix-during-call, revert-on-call-end, media-services-reset-during-idle) remains pending on physical hardware.
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
|---|---|
|
||||
| DEC-012 legal/trademark/OSS review | Explicitly open — `v1.0.0-rc.1` is the candidate awaiting sign-off. Public release is blocked. |
|
||||
| Android Keystore-backed DEK | Deferred to v1.1. Android still uses file-fallback for the Data Encryption Key. |
|
||||
| iOS `AVAudioSession.Mode.voiceChat` | Implemented in `apps/chanora_flutter/ios/Runner/AppDelegate.swift`; release readiness still requires device audio validation and candidate evidence attachment. |
|
||||
| iOS `AVAudioSession.Mode.voiceChat` | Implemented in `apps/chanora_flutter/ios/Runner/AppDelegate.swift` with call-scoped activation (idle `.ambient` baseline; VoIP `.playAndRecord` + `.voiceChat` + `.mixWithOthers` engaged only on `BridgeEvent::AudioStarted` via `chanora/ios_audio_session` MethodChannel). Release readiness still requires device audio validation and candidate evidence attachment. |
|
||||
| Candidate state-sync evidence attachment | Reducer tests exist and pass locally; release readiness still needs candidate CI/run IDs and runtime integration evidence attached before public release approval. |
|
||||
|
||||
---
|
||||
|
||||
+1
-1
@@ -1317,7 +1317,7 @@ Therefore:
|
||||
- Analysis: Feasible with current Flutter + Rust Core architecture; refine in SAD/SDD as needed.
|
||||
- Owner: Software Team
|
||||
|
||||
**SRS-110**: The iOS software shall integrate with AVAudioSession or equivalent platform audio session behavior for foreground voice sessions.
|
||||
**SRS-110**: The iOS software shall integrate with AVAudioSession or equivalent platform audio session behavior for foreground voice sessions. The session shall be configured for VoIP (`.playAndRecord` + `.voiceChat` + `.mixWithOthers`) only while a voice channel is active, and shall return to a non-disruptive idle state (`.ambient`, inactive, with `.notifyOthersOnDeactivation`) at all other times so that other apps' audio (music, podcasts, navigation) is preserved when the user opens Chanora to read text chat.
|
||||
|
||||
- Type: Platform / iOS
|
||||
- Stage: P0 / MVP
|
||||
|
||||
+1
-1
@@ -1353,7 +1353,7 @@ External Server -> Protocol Adapter -> Rust Core -> State Engine -> Bridge -> Fl
|
||||
| Protocol compatibility | SE-05, SE-11 | `tsclientlib` adapter, protocol probe, compatibility matrix |
|
||||
| Secure identity handling | SE-03, SE-16 | Platform secure storage, no plaintext private keys |
|
||||
| Diagnostic privacy | SE-17, SE-19 | Redaction before export, user-initiated export |
|
||||
| Mobile foreground voice | SE-03, SE-14 | AVAudioSession, Android foreground service, lifecycle handling |
|
||||
| Mobile foreground voice | SE-03, SE-14 | AVAudioSession (call-scoped VoIP activation with `.mixWithOthers`, idle `.ambient` baseline), Android foreground service, lifecycle handling |
|
||||
| Release trust | SE-18 | Signing, notarization, app-store release metadata review |
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user