CallKit was a doorbell. It rang the phone when a VoIP push arrived and
took no further part, which left four things wrong.
Declining from the lock screen did not decline. The end action cleared
the local ring and fulfilled itself, and nothing told the call manager,
so the caller went on listening to a phone that had already said no.
The audio session was never handed over. There was no didActivate and
no didDeactivate, and manual audio was set only on the Simulator, so on
a device WebRTC raced CallKit to bring the session up. Doing that first
is the documented way to get a call that connects and carries no sound.
The unit is now off by default and exactly one thing turns it on:
CallKit for a call it owns, the manager for one placed or answered
inside the app.
Ending a call never told CallKit either, and a call left open there
holds the phone in an in-call state and refuses the next incoming one.
And outgoing calls were invisible to iOS: no Recents entry, no session
ownership, nothing stopping the phone ringing for something else in the
middle of one. They are reported now, connecting and connected.
⚠️ The audio path is reasoned from Apple's and WebRTC's contract and is
NOT observed. A Simulator cannot exercise it, which is why none of this
was noticed. iPhone call audio has never been proven on hardware, and
this is the most likely explanation; it is also the change most in need
of a real device before it is trusted.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>