Attempt to fix ExoPlayer crash#5380
Conversation
There was a problem hiding this comment.
Pull request overview
This PR attempts to prevent a Media3/ExoPlayer ClassCastException crash during seekTo() by deferring seeks until the player’s timeline is initialized (READY/BUFFERING) and adding a defensive try/catch around seekTo().
Changes:
- Defer seeks when ExoPlayer is still in
STATE_IDLE, performing the seek once playback reachesSTATE_BUFFERING/STATE_READY. - Add a
ClassCastExceptioncatch aroundExoPlayer.seekTo()to avoid crashing on the reported Media3 timeline race.
| } | ||
| } | ||
| currentPlayer.addListener(listener) | ||
| if (currentPlayer.isReadyForSeek()) { |
There was a problem hiding this comment.
Could there be an issue if the user changes episodes before isReadyForSeek is true?
There was a problem hiding this comment.
When the user changes episodes, handleStop() calls player.stop() which synchronously transitions the player to STATE_IDLE. The listener catches STATE_IDLE (line 148-149) and removes itself without performing the seek. This cleanup happens before release() is called, so the listener never fires a stale seek on the old player instance.
So in theory everything should be fine.
There was a problem hiding this comment.
as per or discussion, i made another change to only attach the listener when the player is idle 211872d
211872d to
dec0cbf
Compare
|
Version |
Description
Noticed this crash in 8.13-rc-1, see ticket for details.
Claude's investigation:
ExoPlayer.seekTo()internally accesses playbackInfo.periodId.periodUid and passes it toPlaylistTimeline.getPeriodByUid(), which casts it toPair. If the UID is a plainObject(not yet wrapped in a Pair by the PlaylistTimeline), it throwsClassCastException.Why it happens: SimplePlayer.prepare() calls player.setMediaSource(source) then player.prepare(). The prepare() call is asynchronous — it kicks off work on ExoPlayer's internal playback thread. But our code immediately sets prepared = true and proceeds to playIfAllowed(), which calls player.seekTo(). At this point, ExoPlayer's internal playbackInfo may not yet have consistent period UIDs — the internal thread hasn't finished processing, and the masking state between the application thread and the playback thread can be momentarily inconsistent. We're seeking before the player's timeline is actually ready for timeline-dependent operations.
How the fix works:
when the player transitions to BUFFERING/READY. This respects Media3's async prepare contract.
UPDATE
after a discussion with @geekygecko we have decided not to include this fix in 8.13 as it only affected 2 users in the beta cycle. i will change target to
mainand milestone to 8.14Fixes PCDROID-591 https://linear.app/a8c/issue/PCDROID-591/attempt-to-fix-classcastexception-crash-of-exoplayer
Testing Instructions
I was not able to reproduce it :(
Just smoke test playback, seeking, resuming from previous position on cold app start.
Checklist
./gradlew spotlessApplyto automatically apply formatting/linting)modules/services/localization/src/main/res/values/strings.xml