A second device's ring no longer hangs up a call answered on the first #150

Merged
paulhitt merged 2 commits from fix/second-device-hangs-up-answered-call into main 2026-09-11 16:20:59 +00:00
paulhitt commented 2026-09-11 16:16:46 +00:00 (Migrated from gitlab.com)

With one account on two devices, both ring. Answer on one and the other keeps ringing, because nothing tells it. When its ring guard fired it sent the caller an end with reason timeout, and the caller hung up the call in progress. This got much more likely with the iPad build, where one account on a phone and a tablet is the normal case.

Ring guard: releases the ring locally and sends nothing. The caller gives up on its own dial timer long before this fires, so the message was redundant, and on a shared account it was destructive.

End handler: it did not check the call id at all, so any end for any call hung up whatever was current. It now requires the call id to match, and once a call has connected it ignores an end whose reason means the ring was never picked up (declined, busy, timeout). Those can only have come from another device that was ringing: someone silencing it, or a build already in people's hands that still announces its timeout. A plain hang-up carries no such reason and still ends the call.

SecondDeviceCallTest guards both halves where Android CI actually runs it. The iPhone test reads this file too, but only when the checkouts sit side by side under the names it expects, which no CI build directory has. Proven able to fail: both checks fail against the code before the fix.

Not observed on two real devices yet; found by reading the signalling path end to end. JVM suites: 1294 tests, 0 failures.

The iPhone half is the same fix in its own MR.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com

🤖 Generated with Claude Code

With one account on two devices, both ring. Answer on one and the other keeps ringing, because nothing tells it. When its ring guard fired it sent the caller an end with reason `timeout`, and the caller **hung up the call in progress**. This got much more likely with the iPad build, where one account on a phone and a tablet is the normal case. **Ring guard:** releases the ring locally and sends nothing. The caller gives up on its own dial timer long before this fires, so the message was redundant, and on a shared account it was destructive. **End handler:** it did not check the call id at all, so any end for any call hung up whatever was current. It now requires the call id to match, and once a call has connected it ignores an end whose reason means the ring was never picked up (`declined`, `busy`, `timeout`). Those can only have come from another device that was ringing: someone silencing it, or a build already in people's hands that still announces its timeout. A plain hang-up carries no such reason and still ends the call. `SecondDeviceCallTest` guards both halves where Android CI actually runs it. The iPhone test reads this file too, but only when the checkouts sit side by side under the names it expects, which no CI build directory has. Proven able to fail: both checks fail against the code before the fix. Not observed on two real devices yet; found by reading the signalling path end to end. JVM suites: **1294 tests, 0 failures**. The iPhone half is the same fix in its own MR. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
paulhitt commented 2026-09-11 16:20:59 +00:00 (Migrated from gitlab.com)

mentioned in commit 9e8c1005fe

mentioned in commit 9e8c1005fec95a7179c6c88bac6af878c577fc48
paulhitt (Migrated from gitlab.com) merged commit 9e8c1005fe into main 2026-09-11 16:20:59 +00:00
Sign in to join this conversation.