This system is closer to a B2B institutional device-fleet scenario than a consumer calling app. In healthcare, eldercare, and similar facilities, many shared Android devices may need to stay online for long periods, recover without local troubleshooting, and keep calls usable in noisy rooms where pickup distance and speech quality both matter.
The problem was specific: the same Android WebRTC call flow became unstable on Android 14 when media was forced through a coturn TURN relay. The call could connect, but Android 14 devices often disconnected within 30-60 seconds. Older Android devices were mostly stable.
The investigation could not stop at the noisiest timeout log. It also needed the ICE state timeline, the selected candidate pair, and the TURN server configuration.
Background
The original call path mostly ran inside a private network. Devices could often establish media through host or srflx candidates. After adding public relay support, the path changed:
- The Android WebRTC client handled capture, playback,
PeerConnection, and ICE callbacks. - The signaling service exchanged session state, SDP, and ICE candidates.
coturnhandled TURN relay traffic.- The test goal was to compare stability across Android versions when the media path used relay.

Symptom
After narrowing the reproduction path, the behavior was consistent:
- Android 14 devices often left the call within 30-60 seconds.
- Older Android devices stayed connected under the same test flow.
- A few calls stayed up, which made the issue look intermittent.
- Forcing TURN relay made the issue easier to reproduce.
The call was established first, then failed inside a predictable time window. That moved the investigation from signaling setup to post-connection media path and ICE state changes.
The Misleading Clue
Early logs repeatedly showed timeout errors around local-address relay channel negotiation. The timing was close to the disconnect window, so it was tempting to treat that log as the root cause.
The better signal came from WebRTC state callbacks:
IceConnectionChange -> DISCONNECTED / FAILED
StandardizedIceConnectionChange -> DISCONNECTED / FAILEDThat shifted the question back to WebRTC itself: was the selected candidate pair actually using relay, when did ICE leave the connected state, and did the app exit the call based on that state?

Investigation Steps
1. Force a single media path
In early tests, some devices could still use direct paths. That made the same code run through different network routes depending on the environment.
To reduce noise, the test forced traffic through coturn. The problem changed from “random network instability” into “repeatable failure on the TURN relay path”.
2. Rule out the WebRTC SDK version
The next suspect was the WebRTC library or Android SDK compatibility. Updating the WebRTC dependency did not remove the failure on the same path, so a simple SDK upgrade was not enough.
3. Compare Android versions and firmware
The device matrix pointed toward Android 14:
- Some Android 14 firmware builds failed much more often.
- Several older Android devices stayed stable.
- The failure correlated strongly with TURN relay usage.
At that point, the question became whether Android 14 was more sensitive to certificate, security, or port settings in the relay path.
4. Recheck coturn and ICE behavior together
The final fix focused on coturn configuration, including certificate handling, security-related options, and required port exposure. After those changes, the same device matrix no longer reproduced the 30-60 second disconnect.
The careful conclusion is:
In this test matrix, Android 14 devices were more sensitive to TURN relay certificate, security, and port configuration. After tightening the coturn setup, the disconnect disappeared.
Debugging Order
This is the order I would use next time:
| Step | Check | Why it matters |
|---|---|---|
| 1 | Selected candidate pair: host, srflx, or relay | Confirm the real media path first |
| 2 | IceConnectionChange and StandardizedIceConnectionChange timeline | Verify when the connection actually degraded |
| 3 | Client behavior in the first 30-60 seconds | Separate media failure, app exit logic, and signaling state changes |
| 4 | Android version, firmware, and WebRTC SDK matrix | See whether the issue concentrates on one device class |
| 5 | coturn certificate, security options, and TURN/TLS/TCP/UDP ports | Validate the relay service path |
The example keeps only the debugging direction and omits deployment details.

Reusable Checklist
- Record Android version, firmware version, WebRTC library version, and network type for both sides.
- Confirm whether the selected candidate pair is host, srflx, or relay.
- Keep the full
IceConnectionChangeandStandardizedIceConnectionChangetimeline. - Force TURN relay when the goal is to isolate relay behavior.
- Check
coturncertificate, security options, and exposed ports. - Retest with the same devices, network, and call duration before and after the fix.
Takeaway
The useful lesson was the order of investigation. A high-frequency timeout log may be useful, but it is not automatically the root cause. For WebRTC disconnects, first confirm the actual media path, then inspect the ICE state timeline, then compare client versions and relay configuration.
Open to Go/WebRTC/RTC Gateway roles. I am also interested in practical debugging notes around Android WebRTC, coturn, TURN relay, and RTC Gateway reliability.
