Skip to content

ForwardingSimpleBasePlayer throws exception due to invalid isLoading state during stop() #2133

Closed
@samaudi

Description

@samaudi

Version

Media3 1.5.1

More version details

No response

Devices that reproduce the issue

Samsung Galaxy Note20 Ultra running Android 13
Samsung S23 Ultra running Android 14

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Not tested

Reproduction steps

  1. Integrate the library to play video streams using an ExoPlayer instance (which works correctly on its own).
  2. Replace the direct ExoPlayer usage with a ForwardingSimpleBasePlayer without any overrides.
  3. Start playback of a online streaming media item.
  4. Call the stop() method on the player.
  5. Observe the state transitions logged by ExoPlayer via Player.Listener.onEvents(), which report the following sequence:

ExoPlayer State changed. playbackState=STATE_IDLE, isLoading=true
ExoPlayer State changed. playbackState=STATE_IDLE, isLoading=true
ExoPlayer State changed. playbackState=STATE_IDLE, isLoading=false

  1. During these transitions, ForwardingSimpleBasePlayer.getState() passes the playback state and the isLoading flag directly to a SimpleBasePlayer.StateBuilder. When StateBuilder.build() is called, the constructor from SimpleBasePlayer.State() runs a check:
if (builder.playbackState == Player.STATE_IDLE || builder.playbackState == Player.STATE_ENDED) {
    checkArgument(!builder.isLoading, "isLoading only allowed when not in STATE_IDLE or STATE_ENDED");
}
  1. Because the builder receives isLoading=true while the playback state is STATE_IDLE, the check fails and an exception is thrown.

Expected result

The player should update its state without throwing an exception. In particular, when transitioning (e.g., after a stop() call on a stream), the state reported by ForwardingSimpleBasePlayer should correctly handle the isLoading flag—either by ensuring it is false when in STATE_IDLE/STATE_ENDED or by adjusting the check logic—so that no exception occurs.

Actual result

An exception is thrown with the message:
"isLoading only allowed when not in STATE_IDLE or STATE_ENDED"
This occurs because ForwardingSimpleBasePlayer.getState() transfers the playback state and isLoading flag directly to the StateBuilder, and when the underlying ExoPlayer reports STATE_IDLE with isLoading=true during a stop transition, the check in StateBuilder’s constructor fails. Consequently, the ForwardingSimpleBasePlayer becomes unusable in this scenario.

Stacktrace after Player.stop() call:
java.lang.IllegalArgumentException: isLoading only allowed when not in STATE_IDLE or STATE_ENDED
at androidx.media3.common.util.Assertions.checkArgument(Assertions.java:55)
at androidx.media3.common.SimpleBasePlayer$State.(SimpleBasePlayer.java:1027)
at androidx.media3.common.SimpleBasePlayer$State.(SimpleBasePlayer.java:101)
at androidx.media3.common.SimpleBasePlayer$State$Builder.build(SimpleBasePlayer.java:809)
at xxx.xxx.xxx.xxx.xxx.core.player.media3.video.ForwardingSimpleBasePlayer.getState(ForwardingSimpleBasePlayer.java:172)
at androidx.media3.common.SimpleBasePlayer.invalidateState(SimpleBasePlayer.java:3036)
at xxx.xxx.xxx.xxx.xxx.core.player.media3.video.ForwardingSimpleBasePlayer.access$000(ForwardingSimpleBasePlayer.java:27)
at xxx.xxx.xxx.xxx.xxx.core.player.media3.video.ForwardingSimpleBasePlayer$1.onEvents(ForwardingSimpleBasePlayer.java:89)
at androidx.media3.exoplayer.ExoPlayerImpl.lambda$new$0$androidx-media3-exoplayer-ExoPlayerImpl(ExoPlayerImpl.java:296)
at androidx.media3.exoplayer.ExoPlayerImpl$$ExternalSyntheticLambda15.invoke(D8$$SyntheticClass:0)
at androidx.media3.common.util.ListenerSet$ListenerHolder.iterationFinished(ListenerSet.java:353)
at androidx.media3.common.util.ListenerSet.handleMessage(ListenerSet.java:297)
at androidx.media3.common.util.ListenerSet.$r8$lambda$rFcF5Pkb99AL585p5-2u78YfNkY(Unknown Source:0)
at androidx.media3.common.util.ListenerSet$$ExternalSyntheticLambda0.handleMessage(D8$$SyntheticClass:0)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

Media

Not applicable

Bug Report

  • You will email the zip file produced by adb bugreport to [email protected] after filing this issue.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions