Increase in `ERROR_CODE_FAILED_RUNTIME_CHECK=1004` errors after seek on Android 14 since 1.3.0
Version
Media3 1.3.0
- The number of errors has grown ~3-4 times after the update from 1.2.0 to 1.3.0
- We will update to 1.4.0 in the near future to see if that helps
More version details
No response
Devices that reproduce the issue
We were not able to reproduce the issue locally yet, but here are some stats from production.
The issue is most prominent on Android 14:
Devices:
| Device | Occurrences over last 30 days (unique) |
|---|---|
| SM-X200 | 14,885 |
| SM-P613 | 9,367 |
| SM-A525M | 7,118 |
| CPH2363 | 6,109 |
| SM-A135M | 6,082 |
| moto g84 5G | 5,732 |
| SM-A235M | 5,542 |
| moto g53 5G | 5,249 |
| 23043RP34G | 5,211 |
| motorola edge 30 neo | 3,859 |
| A063 | 3,275 |
| SM-X205 | 2,615 |
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
Based on the user behavior, most users face this issue after seeking the video. Examples:
Expected result
The media plays successfully.
Actual result
Playback crashes with the ERROR_CODE_FAILED_RUNTIME_CHECK=1004 error.
Unexpected runtime error at q2.J.handleMessage(ExoPlayerImplInternal.java:293)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:257)
at android.os.Looper.loop(Looper.java:368)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: android.media.MediaCodec$CodecException:
at android.media.MediaCodec.native_flush(Native Method)
at android.media.MediaCodec.flush(MediaCodec.java:2504)
// ... the rest of the stacktrace is obfuscated
The diagnostic info is: android.media.MediaCodec.error_neg_110
https://developer.android.com/reference/android/media/MediaPlayer#MEDIA_ERROR_TIMED_OUT
Media
DASH H.264, Widevine
Bug Report
- [ ] You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
Does this problem only happen for Widevine protected content? (You may not be able to say that if your app doesn't play anything else).
The most suspicious change that could make a difference for 1.3.0+ and Android 14+ specifically is https://github.com/androidx/media/commit/e5aa69237eb7a47e81611398d2be21faba5e53c0.
Could you try calling DefaultRenderersFactory.experimentalSetMediaCodecAsyncCryptoFlagEnabled(false) when setting up the player to see if it makes a difference? The customized DefaultRenderersFactory can be injected into ExoPlayer.Builder.setRenderersFactory.
Does this problem only happen for Widevine protected content? (You may not be able to say that if your app doesn't play anything else).
The app only plays Widevine DRM-protected content, so I can't say if it happens for anything else.
Could you try calling
DefaultRenderersFactory.experimentalSetMediaCodecAsyncCryptoFlagEnabled(false)when setting up the player
Thank you for the suggestion 👍 We have set this flag to false and I will come back with updates once we have more production data.
Hello @tonihei, it looks like setting DefaultRenderersFactory.experimentalSetMediaCodecAsyncCryptoFlagEnabled to false does seem to help. We see a decrease in the 1004 errors to the level of pre-media3-1.3.0.
Thanks for the verification! It looks like there might be a bug in the Android platform implementation of this performance optimization then. I'll try to follow up with the relevant team to see if there is something we can do. [internal ref: b/362450802]
I can confirm exactly the same behavior on a Samsung SM-X200, we can consistently reproduce the issue on version 1.5.0 (we upgraded from 1.2.0 and see the problem since then).
We play a mixture of plain mp4's in a playlist together with Widevine L1 protected DASH streams. Every time we seek in the DASH stream, we get exactly the same playback failure and stacktrace as in the issue description.
I can confirm that calling experimentalSetMediaCodecAsyncCryptoFlagEnabled(false) solves the issue in our case, too.
@tonihei Do you happen have any update regarding this issue? It feels slightly uncomfortable to rely on an experimental flag to fix playback issues in production.
There is no update from the relevant platform team yet I'm afraid. Since the feature doesn't seem to be reliable, I'm going to flip the default back to "don't use it" until we get more information when a fix will be available.
It feels slightly uncomfortable to rely on an experimental flag to fix playback issues in production.
Forgot to address this part: The method is "experimental" because we intend to remove it without further deprecation as soon as we are satisfied that no setter is needed. But it simply turns the feature on and off, so it's safe to use (just be prepared for it to disappear in a future update of the library).
we can consistently reproduce
@maartenvgpersgroep Does that mean you have a reproducible example on a local test device (and not just reports from users)? If so, is there a way to share the reproduction steps with us and/or provide a bugreport after the issue? You can send information to [email protected] with "Issue #1641" in the subject if needed and report back here once you've done that. If we have a way to directly reproduce the issue it's much more likely to find a root cause and fix.
@tonihei I have double-checked with our QA, and we cannot reproduce the issue consistently and reliably, but we can reproduce it often. Sometimes it fails a couple of times in a row, sometimes it doesn't happen at all. But it's reproducible enough to capture a bug report.
I have sent an email with our setup, reproduction steps as well as a bugreport to [email protected].
I hope it helps.
Thanks for the additional information! I forwarded that to the platform team, so hopefully it's helpful to investigate the issue.
As follow-up question on this topic, what is not really clear, does this issue affect only and exclusively Android 14, or all Android versions are affected? Thanks.
As follow-up question on this topic, what is not really clear, does this issue affect only and exclusively Android 14, or all Android versions are affected? Thanks.
We are using Media3 version 1.4.1 and have seen this happen on other Android versions too, for example:
- Android 15 - Redmi 23108RN04Y
- Android 13 - Redmi 23124RA7EO
We are also facing this issue. It happens only with long hours of playback. It is happening in firestick devices.
Media 3 version : 1.3.1
Caused by java.lang.IllegalArgumentException: at android.media.MediaCodec.native_setSurface(MediaCodec.java) at android.media.MediaCodec.setOutputSurface(MediaCodec.java:1998) at androidx.media3.exoplayer.drm.FrameworkMediaDrm$$ExternalSyntheticApiModelOutline0.m() at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.setOutputSurface(SynchronousMediaCodecAdapter.java:191) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutputSurfaceV23(MediaCodecVideoRenderer.java:1776) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.setOutput(MediaCodecVideoRenderer.java:826) at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.handleMessage(MediaCodecVideoRenderer.java:744) at androidx.media3.exoplayer.ExoPlayerImplInternal.deliverMessage(ExoPlayerImplInternal.java:1698) at androidx.media3.exoplayer.ExoPlayerImplInternal.sendMessageToTarget(ExoPlayerImplInternal.java:1662) at androidx.media3.exoplayer.ExoPlayerImplInternal.sendMessageInternal(ExoPlayerImplInternal.java:1637) at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:575) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:211) at android.os.HandlerThread.run(HandlerThread.java:65)
There have been some fixes in the Android platform that may address this issue, it's not fully clear though because the platform team was never able to reproduce the issue themselves. If someone here has a good way of running an experiment to see if it's fixed, it might be worth checking if you can set experimentalSetMediaCodecAsyncCryptoFlagEnabled(true) on Android 16 (API 36+) without causing the same issue again.
@maartenvgpersgroep and @egor-n You both mentioned previously that you can consistently reproduce/observe the issue. As per my post above, the Android platform team thinks the issue is resolved from Android 16 (API36+). Do you think you can try to call experimentalSetMediaCodecAsyncCryptoFlagEnabled(true) on devices with API36+ to verify the issue is gone? Thanks for your help!
Hi @tonihei, sure. We will ship the next update of our app with experimentalSetMediaCodecAsyncCryptoFlagEnabled(Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM). I can't comment on how quickly this will ship to production, probably in more than a week, but we'll monitor if this causes the regression in playback failures again (or not, hopefully) and will let you guys know.
@maartenvgpersgroep API 36+ should be BAKLAVA if you want to use a named constant, not VANILLA_ICE_CREAM (that was API 35)
Hi @tonihei , it took some time to reach production and gain user adoption, but I'm happy to report that calling experimentalSetMediaCodecAsyncCryptoFlagEnabled(true) on API36+ does not increase our playback failure rate. I have to say though, that the percentage (and even absolute amount) of our users running Android 16 is very very small. In total we had 466 video views on Android 16, of which none failed with ERROR_CODE_FAILED_RUNTIME_CHECK (compared to a total of 408.391 views overall with this change in place). So maybe take it with a grain of salt, but the initial impression raises no red flags.
Amazing, thanks a lot for running this verification!
Just to be sure though - based on the previous error rates, do you think it's likely you would have seen the issue already if it was still there? And did these users running Android 16 include Samsung and Motorola per the original device list above (just in case there is something specific about the codecs on these devices that triggered the issue)?
In any case, it sounds like we can turn the feature back on guarded by the API 36 check.
Hard to say really - that's why I mentioned it. Statistically it's hard to draw conclusions from such a small sample size. The fact that there were zero ERROR_CODE_FAILED_RUNTIME_CHECK errors on Android 16 could mean something.
None of the devices that were affected by this problem (there's a table in the initial issue) have received an update to Android 16. All of those devices still run Android 14 probably, and had the issue fixed for them by setting the experimentalSetMediaCodecAsyncCrypto flag to false. When looking at our views, all Android 16 playback sessions were exclusively Google Pixel devices, and one user with a Xiaomi 14T Pro. So no, there were no Samsung or Motorola devices included here. Simply because there's no Android 16 for those just yet.
There's really only one way to find out if this will work, and that's by turning the flag back on on Android 16+. That's the only way we can get any feedback. We monitor our analytics closely so we can always report if we see a downwards trend in stability again.
That makes sense - so you are planning to keep the flag enabled for Android 16 and then we hopefully get more device coverage soon? The earliest we can release our updated default logic is with Media3 1.9.0 (~October) anyway, so we can also wait a bit with flipping the default back on.
Yes - it didn't break anything so we're fine to keep it like this in prod, until it does break and starts to hurt us.
@maartenvgpersgroep, do you have any recent reports of this crash on Android 16? By now the OS should have rolled out to more devices, including Samsung. If there are no crashes, we could flip the default back to on for Android 16+
Hi @tonihei , we've seen 17 of these errors on Android 16 devices, on a total of 57913376 views. So I think it's safe to say that it's okay to flip the default back to on 😄
Sounds great, thanks for the quick confirmation!