Audio session fixes #61
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
iOS CallKit Audio Session Race Condition Fix - PR Description
Incoming calls on iOS with CallKit were failing because of a race condition between WebRTC (used internally by Siprix) and CallKit competing for audio session control. WebRTC needs to initialize audio immediately when the SIP INVITE arrives (to generate the SDP answer), but CallKit expects to control when the audio session activates. When WebRTC wins the race, iOS doesn't call the
didActivatecallback, which means we never actually accept the call even though the UI shows "connected".Changes
1. Defer SIP Accept Until didActivate
Instead of accepting the SIP call immediately in
CXAnswerCallAction, we now:_callPendingAnswerdidActivateto fireWhy it's critical: Accepting the call before the audio session is ready leads to no audio routing. iOS needs to know the audio path exists before the SIP connection completes.
2. Fulfill CXAnswerCallAction Immediately
Fulfill the action right away to tell CallKit we're ready to proceed:
Why it's critical: If we don't fulfill, CallKit won't proceed with audio activation, so
didActivatenever fires and we're stuck waiting forever.3. Force Reset Interrupted Audio Sessions
In
didActivate, detect when WebRTC has already activated the audio session:Why it's critical: WebRTC activating audio before CallKit leaves the session in an "interrupted" state. Resetting clears this and lets us reconfigure for VoIP properly.
4. Audio Configuration in didActivate (Not onSipConnected)
Added
ensureAudioSessionConfigured()method that sets up VoIP audio settings:Called from
didActivate(before SIP accept), notonSipConnected(after connection).Why it's critical: Configuring audio AFTER the SIP connection is too late - iOS has already determined there's no audio path. Must happen in
didActivatewhich fires BEFORE we send the SIP accept.Why This Approach
We can't prevent WebRTC from initializing early - it's required for SIP to work (needs to check hardware capabilities to generate the SDP answer). So instead, we work around it:
The deferred answer pattern ensures everything happens in the right order: fulfill action → activate session → configure audio → accept call. Doing it any other way leaves the audio routing broken.
@siprix let me know your thoughts on whether this is all appropriate or not. After these changes ive personally noticed a dramatic increase in call reliability when receiving a call from the foreground/background and from an app killed state.