Android PlatformAudio: total silence due to missed RegisterAudioCallback on the lazily-created platform ADM
Summary
On Android, using PlatformAudio (the WebRTC ADM path) can result in complete silence for both mic capture and remote playout, with no errors anywhere — WebRTC, the Android audio HAL, and dumpsys audio/dumpsys media.audio_flinger all report a fully healthy pipeline (players created and started, buffers full, zero underruns, correct routing, no muting). Root cause is a timing gap between AdmProxy::RegisterAudioCallback() and the lazy creation of the Android platform ADM.
Root cause
AdmProxy::RegisterAudioCallback() (webrtc-sys/src/adm_proxy.cpp) is called once by WebRTC's engine, forwarding the real webrtc::AudioTransport* only to ADMs that already exist at that moment. On Android, platform_adm_ is created lazily inside EnsurePlatformAdmCreated(), triggered by the app's first AcquirePlatformAdm() (i.e. when PlatformAudio is constructed) - deliberately deferred for JNI-readiness. If WebRTC's one-time callback registration happens before the app creates PlatformAudio (the normal case), platform_adm_ doesn't exist yet, so it never receives the callback. It's later created and started successfully, but with nothing wired to the real audio transport — so it runs indefinitely, writing silence instead of decoded audio.
Fix
In EnsurePlatformAdmCreated(), after platform_adm_->Init() succeeds, backfill the registration:
if (audio_transport_) {
platform_adm_->RegisterAudioCallback(audio_transport_);
}
Tested fix in own application by rebuilding the rust library.
Suggested diagnostic (optional)
Consider a warning log if RegisterAudioCallback() runs with platform_adm_ still null on Android — this failure mode is otherwise silent and very hard to diagnose without source-level instrumentation.
Android PlatformAudio: total silence due to missed RegisterAudioCallback on the lazily-created platform ADM
Summary
On Android, using PlatformAudio (the WebRTC ADM path) can result in complete silence for both mic capture and remote playout, with no errors anywhere — WebRTC, the Android audio HAL, and dumpsys audio/dumpsys media.audio_flinger all report a fully healthy pipeline (players created and started, buffers full, zero underruns, correct routing, no muting). Root cause is a timing gap between AdmProxy::RegisterAudioCallback() and the lazy creation of the Android platform ADM.
Root cause
AdmProxy::RegisterAudioCallback() (webrtc-sys/src/adm_proxy.cpp) is called once by WebRTC's engine, forwarding the real webrtc::AudioTransport* only to ADMs that already exist at that moment. On Android, platform_adm_ is created lazily inside EnsurePlatformAdmCreated(), triggered by the app's first AcquirePlatformAdm() (i.e. when PlatformAudio is constructed) - deliberately deferred for JNI-readiness. If WebRTC's one-time callback registration happens before the app creates PlatformAudio (the normal case), platform_adm_ doesn't exist yet, so it never receives the callback. It's later created and started successfully, but with nothing wired to the real audio transport — so it runs indefinitely, writing silence instead of decoded audio.
Fix
In EnsurePlatformAdmCreated(), after platform_adm_->Init() succeeds, backfill the registration:
Tested fix in own application by rebuilding the rust library.
Suggested diagnostic (optional)
Consider a warning log if RegisterAudioCallback() runs with platform_adm_ still null on Android — this failure mode is otherwise silent and very hard to diagnose without source-level instrumentation.