Repository navigation
ExoPlayer can report isLoading=true in STATE_ENDED, crashing ForwardingSimpleBasePlayer / CastPlayer #3467
Description
Version
Media3 1.11.1
More version details
Also seen on 1.10.1
We use CastPlayer.Builder().setLocalPlayer(exoPlayer), so the local ExoPlayer is wrapped in a ForwardingSimpleBasePlayer.
Devices that reproduce the issue
Various devices and Android versions in production. 9 within 30 minutes, across three app versions from users who were casting a live HLS stream. It seems the HLS stream was being restarted in this period, causing the crash.
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
We have not been able to reproduce it locally. The users were most likely listening to a live HLS audio stream when it crashed.
Expected result
ExoPlayer never reports isLoading() == true while getPlaybackState() is STATE_IDLE or STATE_ENDED, as required by SimpleBasePlayer.State.
Actual result
Fatal Exception: java.lang.IllegalArgumentException: isLoading only allowed when not in STATE_IDLE or STATE_ENDED
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:143)
at androidx.media3.common.SimpleBasePlayer$State.<init>(SimpleBasePlayer.java:1073)
at androidx.media3.common.SimpleBasePlayer$State.<init>(SimpleBasePlayer.java:101)
at androidx.media3.common.SimpleBasePlayer$State$Builder.build(SimpleBasePlayer.java:844)
at androidx.media3.common.ForwardingSimpleBasePlayer.getState(ForwardingSimpleBasePlayer.java:188)
at androidx.media3.cast.CastPlayerImpl.getState(CastPlayerImpl.java:87)
at androidx.media3.common.SimpleBasePlayer.invalidateState(SimpleBasePlayer.java:3178)
at androidx.media3.common.ForwardingSimpleBasePlayer$PlayerListener.onEvents(ForwardingSimpleBasePlayer.java:532)
at androidx.media3.exoplayer.ExoPlayerImpl.lambda$new$0(ExoPlayerImpl.java:323)
at androidx.media3.common.util.ListenerSet$ListenerHolder.iterationFinished(ListenerSet.java:477)
at androidx.media3.common.util.ListenerSet.handleMessage(ListenerSet.java:421)
at android.os.Handler.dispatchMessage(Handler.java:128)
...
The event comes from the local ExoPlayer, so it reported isLoading == true together with STATE_IDLE or STATE_ENDED.
Looking at the 1.11.1 sources, a likely path is ExoPlayerImplInternal.doSomeWork():
if (finishedRendering && playingPeriodHolder.info.isFinal) {
setState(Player.STATE_ENDED);
stopRenderers();
}setState only copies the playback state, and isLoading stays at whatever updateIsLoading() set earlier in the same iteration (shouldContinueLoading || loadingPeriod.mediaPeriod.isLoading()). If the loading period is still loading when the final period finishes rendering, the ENDED update is published with isLoading == true. Because doSomeWork() returns early in STATE_ENDED, it is not corrected afterwards. The other setState(STATE_ENDED) call sites go through resetInternal(), which sets isLoading to false, and ExoPlayerImpl.maskPlaybackState() also clears it, so this path seems to be the odd one out.
This looks similar to #2873 (fixed in 1.10.0), but that fix is already in the versions we see the crash on.
Media
Live HLS audio streams (not publicly shareable test case available at the moment).
Bug Report
- You will email the zip file produced by
adb bugreportto android-media-github@google.com after filing this issue.
Activity