Environment: Vega SDK 0.22.6759
Setup: A React Native app renders two top-level @amazon-devices/webview instances as siblings:
- a lightweight menu/navigation web app with no media playback (used to switch between streams), and
- a video player web app using hls.js + Widevine EME to play L1/CENC DRM streams (DRM handled by the WebView’s Chromium CDM, not the native media pipeline).
We show one at a time and swap between them (menu ↔ video).
How we switch: The menu WebView stays mounted and is toggled with display:none. The player WebView is unmounted (removed from the React tree) when hidden and mounted when shown, and a stream change remounts it (via a React key) to get a clean player instance. So each menu↔video toggle and each stream switch tears down and/or recreates the DRM/EME WebView. (We also tried keeping it mounted and hiding it via opacity:0 / off-screen to avoid the teardown — see below — but those don’t hide it correctly.)
What works: both WebViews coexist and render; the player plays Widevine DRM incl. L1; steady-state playback is stable.
What fails: transitioning between the two WebViews — switching the playing stream, or toggling menu↔video — intermittently kills the renderer, and the app then aborts (SIGTRAP) with:
FATAL:kepler_common/content/browser/renderer_kill_event_observer.cc:32]
RendererService died, killing browser process
preceded by:
WARNING:...child_process_launcher_helper_kepler_single_renderer.cc:71]
Stopping rendererService, but its not needed because AIPC conn is already closed
It often succeeds a few times before dying, suggesting resource accumulation.
Crashing-thread backtrace (symbolicated):
#0 logging::LogMessage::HandleFatal(...) libkepler_slatium.so
#1 logging::LogMessage::Flush() libkepler_slatium.so
#2 logging::LogMessageFatal::~LogMessageFatal() libkepler_slatium.so
#3 ?? libkepler_webview.so ← FATAL raised here
#4–#11 ?? libkepler_slatium.so (stripped Chromium frames)
#12 orpheus::framework::async::onMsgCb(...) libasync.so.0
#13 aceAsyncLoop_run() libasync.so.0
#14–#17 stem_init_main_c (+ frames) libstem_init.so
We also can’t cleanly hide one WebView while the other keeps playing: opacity:0 doesn’t hide the surface (it keeps compositing on top); display:none/unmount crashes while EME is active; moving it off-screen leaves the previously-occluded player’s video surface black on return.
Questions:
- Is running two top-level WebViews, one with an active DRM/EME video pipeline, a supported configuration on Kepler? Is the single shared renderer expected to remain stable under this load?
- Is the renderer death on stream switch / WebView swap a known issue, and is it addressed in a newer SDK/OS build?
- We currently unmount/remount the player WebView on hide and on stream switch. Is that the wrong approach for a DRM WebView on a shared renderer? Is there a supported way to keep the WebView alive and just hide/detach it (a WebView equivalent of native surface detach/attach), rather than tearing it down? Relatedly, is
opacity/off-screen expected to hide a WebView surface, or is that unsupported for GPU-composited surfaces? - Any guidance on releasing renderer resources between DRM stream loads to avoid accumulation?