[Scummvm-tracker] [ScummVM :: Bugs] #17216: ANDROID: audio stops permanently mid-game with the Oboe backend (2026.3.0)

ScummVM :: Bugs trac at scummvm.org
Sun Sep 20 05:42:44 UTC 2026


#17216: ANDROID: audio stops permanently mid-game with the Oboe backend (2026.3.0)
----------------------------+--------------------------------
Reporter:  black-square     |      Owner:  (none)
    Type:  defect           |     Status:  new
Priority:  normal           |  Component:  Audio
 Version:                   |   Keywords:  android audio oboe
    Game:  Monkey Island 1  |
----------------------------+--------------------------------
 === Summary

 Since 2026.3.0, all audio occasionally stops during gameplay and never
 comes back. The game itself keeps running normally — graphics, input and
 saving are unaffected. The only way to get sound back is to quit ScummVM
 and relaunch it. It happens quite often with no obvious trigger: no
 headset plugged or unplugged, no incoming call, no other app playing
 audio.

 2026.3.0 is the first release containing the new Oboe audio backend
 (#7164, 1fd96b5).

 === Environment
 - ScummVM 2026.3.0, official APK, arm64-v8a
 - Samsung Galaxy S23 Ultra (SM-S918U1), Android 16
 - Monkey Island 1 SE (talkie), SCUMM engine

 == WARNING: LLM Analysis below (I didn't verify it)

 The stream is AAudio:

 ```
 Got new stream AAudio -> 0xb4000073192dbe00
 Setting up ring buffer with capacity: 3072
 Setting up mixer with settings sample rate: 48000 and buffer: 96
 ```

 During completely normal play, the stream is torn down and restarted
 constantly:

 ```
 00:00:43.112  Silence 93494+2506: pausing audio stream
 00:00:51.950  Silence 96249+0: pausing audio stream
 00:00:59.217  Silence 97357+757: pausing audio stream
 00:01:06.693  Silence 96205+755: pausing audio stream
 00:01:13.311  Silence 95341+755: pausing audio stream
 00:01:33.355  Silence 96493+755: pausing audio stream
 ```

 Six pause/restart cycles in 90 seconds — one every 7–9 seconds

 Worth noting what those two numbers are: `underflows` is around 96000
 while `silence_count` is only 0–2506. So the 2-second pause threshold is
 being reached almost entirely through ring-buffer *starvation*, not
 through the mixer producing silence. `MixerImpl::mixCallback()` returns 0
 when no channel is active, so `produced(0)` is called and nothing enters
 the ring buffer. In an adventure game that is most of the time, which is
 why the cycle rate is so high.

 === Why I think the stream dies and is never recovered

 This part is reading the code, not something I have proven:

 1. The stream is opened with `SharingMode::Exclusive` +
 `PerformanceMode::LowLatency`, i.e. the AAudio MMAP exclusive path, which
 is the most fragile with respect to route changes. Oboe's own
 [TechNote_Disconnect](https://github.com/google/oboe/wiki/TechNote_Disconnect)
 specifically lists Samsung devices failing to report MMAP disconnects.

 2. No error callback is installed — `initStream()` only calls
 `setDataCallback(this)`. Per that same tech note, the documented way to
 learn about a disconnect when using a data callback is
 `AudioStreamErrorCallback::onErrorAfterClose()`. Without it, the backend
 depends entirely on polling `stream->getState()`.

 3. The Java-side disconnect workaround (`PluginBroadcastReceiver` in
 `ScummVMActivity.java`, the only caller of `notifyAudioDisconnect()`)
 registers itself only on API 28–29, so it is inactive on this device. It
 also only watches headset-plug and USB attach/detach, so Bluetooth route
 changes are never reported on any API level.

 4. If a stream ends up dead while still reporting `Started`,
 `audioThreadFunc()` has no way out. Once the ring buffer is full it does
 `nanosleep(&tv_chunk, nullptr); continue;` with no timeout, so it spins
 there indefinitely feeding a stream nobody drains. That matches the
 symptom exactly: audio gone, game fine, nothing logged, no error surfaced
 anywhere.

 Putting a timeout on that particular wait would make the failure self-
 correcting regardless of whether the disconnect is ever reported, since
 `STREAM_RECREATE()` right below already does the right thing. I have not
 been able to build and test anything, so I'm only pointing at it rather
 than suggesting a specific change.
-- 
Ticket URL: <https://bugs.scummvm.org/ticket/17216>
ScummVM :: Bugs <https://bugs.scummvm.org>
ScummVM


More information about the Scummvm-tracker mailing list