From 3d5946d7cf297e1703f936eabd88d23ef2b23f81 Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:21:14 +0200 Subject: [PATCH 1/2] Log when RegisterAudioCallback runs before the Android platform ADM exists On Android the platform ADM is created lazily in EnsurePlatformAdmCreated(), so it usually does not exist yet when WebRTC performs its one-time AdmProxy::RegisterAudioCallback() registration. In that case the audio transport is only wired to the synthetic ADM; if the app later constructs PlatformAudio the platform ADM is created and started but never receives the transport, running indefinitely while writing silence. This failure mode is otherwise completely silent -- WebRTC, the Android audio HAL, and dumpsys all report a healthy pipeline -- so add a warning log to make it diagnosable from logs alone. Co-Authored-By: Claude Opus 4.8 (1M context) --- webrtc-sys/src/adm_proxy.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/webrtc-sys/src/adm_proxy.cpp b/webrtc-sys/src/adm_proxy.cpp index 209f39d53..de1a845fa 100644 --- a/webrtc-sys/src/adm_proxy.cpp +++ b/webrtc-sys/src/adm_proxy.cpp @@ -297,6 +297,20 @@ int32_t AdmProxy::RegisterAudioCallback(webrtc::AudioTransport* transport) { if (platform_adm_) { platform_adm_->RegisterAudioCallback(transport); } +#if defined(__ANDROID__) + else { + // On Android the platform ADM is created lazily (EnsurePlatformAdmCreated), + // so it usually does not exist yet when WebRTC performs this one-time + // callback registration. If the app later constructs PlatformAudio, the + // platform ADM is created and started but never receives audio_transport_, + // so it runs indefinitely writing silence with no error reported anywhere. + // Log this otherwise-silent condition to make it diagnosable. + RTC_LOG(LS_WARNING) + << "AdmProxy::RegisterAudioCallback() - platform_adm_ is null on " + << "Android; audio transport will not reach the platform ADM if it is " + << "created later. This causes total silence for PlatformAudio."; + } +#endif return 0; } From 25864a7d7cd2847e4c035f4969385256a72decc2 Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:40:54 +0200 Subject: [PATCH 2/2] Backfill audio callback to the lazily-created Android platform ADM AdmProxy::RegisterAudioCallback() is called once, early, by WebRTC's engine and only forwards the real AudioTransport to ADMs that already exist. On Android the platform ADM is created lazily in EnsurePlatformAdmCreated() on the app's first AcquirePlatformAdm() (deferred for JNI readiness), which normally happens after registration. The platform ADM was therefore created and started successfully but with no transport wired up, running indefinitely while writing silence -- total silence for both mic capture and remote playout, with a fully healthy-looking pipeline everywhere (WebRTC, Android audio HAL, dumpsys). Backfill the registration in EnsurePlatformAdmCreated() after Init() succeeds, using the transport retained in audio_transport_. Also soften the diagnostic added in the previous commit from a warning to an info log, since with the backfill in place a null platform_adm_ at registration time is the normal, handled path (and is always expected for synthetic-only usage). Co-Authored-By: Claude Opus 4.8 (1M context) --- webrtc-sys/src/adm_proxy.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/webrtc-sys/src/adm_proxy.cpp b/webrtc-sys/src/adm_proxy.cpp index de1a845fa..b2e73c864 100644 --- a/webrtc-sys/src/adm_proxy.cpp +++ b/webrtc-sys/src/adm_proxy.cpp @@ -131,6 +131,17 @@ bool AdmProxy::EnsurePlatformAdmCreated() { return false; } + // Backfill the audio callback registration. WebRTC performs its one-time + // RegisterAudioCallback() early -- typically before the app constructs + // PlatformAudio and triggers this lazy creation -- so audio_transport_ was + // captured then but never delivered to the platform ADM. Without this the + // platform ADM runs with no transport wired up and writes silence. + if (audio_transport_) { + platform_adm_->RegisterAudioCallback(audio_transport_); + RTC_LOG(LS_VERBOSE) << "AdmProxy: backfilled audio transport to newly " + << "created Android platform ADM"; + } + return true; } #endif @@ -300,15 +311,14 @@ int32_t AdmProxy::RegisterAudioCallback(webrtc::AudioTransport* transport) { #if defined(__ANDROID__) else { // On Android the platform ADM is created lazily (EnsurePlatformAdmCreated), - // so it usually does not exist yet when WebRTC performs this one-time - // callback registration. If the app later constructs PlatformAudio, the - // platform ADM is created and started but never receives audio_transport_, - // so it runs indefinitely writing silence with no error reported anywhere. - // Log this otherwise-silent condition to make it diagnosable. - RTC_LOG(LS_WARNING) - << "AdmProxy::RegisterAudioCallback() - platform_adm_ is null on " - << "Android; audio transport will not reach the platform ADM if it is " - << "created later. This causes total silence for PlatformAudio."; + // so it usually does not exist yet at this one-time registration. The + // transport is retained in audio_transport_ and backfilled to the platform + // ADM when it is created; until then only the synthetic ADM is wired, which + // is the correct state for synthetic-only usage. + RTC_LOG(LS_INFO) + << "AdmProxy::RegisterAudioCallback() - platform_adm_ not yet created " + << "on Android; audio transport retained and will be backfilled when " + << "the platform ADM is created."; } #endif return 0;