Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Null passed to onPlayerError #4262

Closed
FD- opened this issue May 16, 2018 · 7 comments
Closed

Null passed to onPlayerError #4262

FD- opened this issue May 16, 2018 · 7 comments
Assignees
Labels

Comments

@FD-
Copy link

FD- commented May 16, 2018

I'm occasionally seeing null being passed to Player.EventListener's onPlayerError() callback.

Issue description

I'm occasionally seeing null being passed to Player.EventListener's onPlayerError() callback.
The listener is registered on a SimpleExoPlayer instance via the addListener() method.
The documentation doesn't say anything about the meaning of no exception being passed to the callback, and the demo doesn't check for null, so it seems this is not intentional.
Also, as far as I can tell, the issue is only occurring with the newest 2.8.0 (gradle) release of the library.

Reproduction steps

I'm afraid I don't know how this can be reliably reproduced. It seems to happen when the Internet connection drops while playing an HLS live stream.

Link to test content

None at this time

Version of ExoPlayer being used

2.8.0, the newest at the time of writing

Device(s) and version(s) of Android being used

Google Nexus 9, running Android 7.0.1

A full bug report captured from the device

Not captured; Logcat didn't contain much help, as the error propagation through the handler seems to not transport the actual source of the onPlayerError call.

I'm sorry for providing so little details! Wanted to report this nevertheless in case anyone else stumbles upon NullPointerExceptions in onPlayerError.

@andrewlewis andrewlewis self-assigned this May 16, 2018
@andrewlewis
Copy link
Collaborator

This sounds strange. There doesn't seem to be a code path in the library that can cause null to be passed to the event listener (it's always a caught exception instance or a new wrapper around it, passed in ExoPlayerImplInternal). Did you see this in the demo app? If not, is there any chance that the method is being called from somewhere else in the app? If you have logcat captured from when you saw this issue please could you attach it or email it to dev.exoplayer@gmail.com, just in case there are signs of anything else strange going on. Thanks.

@FD-
Copy link
Author

FD- commented May 16, 2018

I did not observe it in the demo app (I did not test it there), but I am sure I'm not calling the listener myself.

This is from the logcat:

05-15 22:49:08.255 30590-30590/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp, PID: 30590
java.lang.NullPointerException: Attempt to read from field 'int com.google.android.exoplayer2.ExoPlaybackException.type' on a null object reference
    at com.myapp.exoplayer.util.PlayerUtil.isBehindLiveWindow(PlayerUtil.java:90)
    at com.myapp.ExoPlayerActivity$2.onPlayerError(ExoPlayerActivity.java:113)
    at com.google.android.exoplayer2.ExoPlayerImpl.handleEvent(ExoPlayerImpl.java:575)
    at com.google.android.exoplayer2.ExoPlayerImpl$1.handleMessage(ExoPlayerImpl.java:106)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

There isn't anything ExoPlayer-related in the logs before or afterwards.

@AquilesCanta
Copy link
Contributor

Is it not possible that your implementation of onPlayerError is calling isBehindLiveWindow with null or that isBehindLiveWindow is doing something different than what the demo app does?

@FD-
Copy link
Author

FD- commented May 16, 2018

I'm calling isBehindLiveWindow() with the ExoPlaybackException passed to onPlayerException(). isBehindLiveWindow() works like the one from the demo:

public static boolean isBehindLiveWindow(ExoPlaybackException e) {
    if (e == null) return false; // Added as workaround for discussed issue

    if (e.type != ExoPlaybackException.TYPE_SOURCE) {
        return false;
    }

    Throwable cause = e.getSourceException();
    while (cause != null) {
        if (cause instanceof BehindLiveWindowException) {
            return true;
        }

        cause = cause.getCause();
    }

    return false;
}

@AquilesCanta
Copy link
Contributor

@FD-, are you able to reproduce locally? As Andrew mentioned, it does not seem there is a codepath that calls onPlayerError with null. If you can reproduce, it'd be great to get a stacktrace at the point at which the message gets sent (shouldn't be that hard in debug mode + a few breakpoints).

@FD-
Copy link
Author

FD- commented May 17, 2018

I was able to reproduce it, and have now gathered more detailed logs. The necessary steps seem to be to play a live HLS stream and disconnect and reconnect the Wifi connection. Please note the app did not crash with an NPE every time, it likely depends on a certain timing. I added the same stream to the demo app, but could not get it to crash, so it's likely something specific to my app.

These are all logs from the crash that seem ExoPlayer related:

Last logs before the issue occurs:

05-17 16:22:38.449 7361-7361/com.myapp D/EventLogger: timelineChanged [31.19, -8.91, window=0, period=0, periodCount=1, windowCount=1, reason=DYNAMIC
      period [?]
      window [30.00, true, true]
    ]
05-17 16:22:53.119 7361-7361/com.myapp D/EventLogger: timelineChanged [45.87, -18.92, window=0, period=0, periodCount=1, windowCount=1, reason=DYNAMIC
05-17 16:22:53.120 7361-7361/com.myapp D/EventLogger:   period [?]
      window [30.00, true, true]
    ]

A bit later:

05-17 16:22:54.597 7361-7361/com.myapp D/EventLogger: state [47.35, -18.92, window=0, period=0, true, READY]

First part of the issue:

05-17 16:23:03.192 7361-7896/com.myapp E/ExoPlayerImplInternal: Source error.
    com.google.android.exoplayer2.source.BehindLiveWindowException
        at com.google.android.exoplayer2.source.hls.HlsChunkSource.getNextChunk(HlsChunkSource.java:286)
        at com.google.android.exoplayer2.source.hls.HlsSampleStreamWrapper.continueLoading(HlsSampleStreamWrapper.java:534)
        at com.google.android.exoplayer2.source.CompositeSequenceableLoader.continueLoading(CompositeSequenceableLoader.java:78)
        at com.google.android.exoplayer2.source.hls.HlsMediaPeriod.continueLoading(HlsMediaPeriod.java:222)
        at com.google.android.exoplayer2.MediaPeriodHolder.continueLoading(MediaPeriodHolder.java:157)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.maybeContinueLoading(ExoPlayerImplInternal.java:1539)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleContinueLoadingRequested(ExoPlayerImplInternal.java:1522)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:322)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:154)
        at android.os.HandlerThread.run(HandlerThread.java:61)

I then see:

05-17 16:23:03.247 7361-7361/com.myapp D/EventLogger: decoderDisabled [55.99, -10.39, window=0, period=0, video]
05-17 16:23:03.262 7361-7361/com.myapp D/EventLogger: decoderDisabled [56.01, -10.39, window=0, period=0, audio]
05-17 16:23:03.264 7361-7361/com.myapp D/EventLogger: mediaPeriodReleased [56.01, -10.39, window=0, period=0]

Then comes the propagation to the listeners:

05-17 16:23:03.282 7361-7361/com.myapp E/EventLogger: playerFailed [56.03, -10.39, window=0]
    com.google.android.exoplayer2.ExoPlaybackException
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:349)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:154)
        at android.os.HandlerThread.run(HandlerThread.java:61)
     Caused by: com.google.android.exoplayer2.source.BehindLiveWindowException
        at com.google.android.exoplayer2.source.hls.HlsChunkSource.getNextChunk(HlsChunkSource.java:286)
        at com.google.android.exoplayer2.source.hls.HlsSampleStreamWrapper.continueLoading(HlsSampleStreamWrapper.java:534)
        at com.google.android.exoplayer2.source.CompositeSequenceableLoader.continueLoading(CompositeSequenceableLoader.java:78)
        at com.google.android.exoplayer2.source.hls.HlsMediaPeriod.continueLoading(HlsMediaPeriod.java:222)
        at com.google.android.exoplayer2.MediaPeriodHolder.continueLoading(MediaPeriodHolder.java:157)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.maybeContinueLoading(ExoPlayerImplInternal.java:1539)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleContinueLoadingRequested(ExoPlayerImplInternal.java:1522)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:322)
        at android.os.Handler.dispatchMessage(Handler.java:98) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.os.HandlerThread.run(HandlerThread.java:61) 

The app then reinitializes the player, in a way very similar to the demo app. I recreate the source (seems this part differs from the demo), and call prepare() (I might seek before preparing, I'm not sure if that part gets called in this case).

It then crashes with:

05-17 16:23:03.388 7361-7361/com.myapp D/EventLogger: loading [56.14, 0.00, window=0, false]
    state [56.14, 0.00, window=0, true, BUFFERING]
05-17 16:23:03.405 7361-7361/com.myapp D/AndroidRuntime: Shutting down VM
05-17 16:23:03.407 7361-7361/com.myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.myapp, PID: 7361
    java.lang.NullPointerException: Attempt to read from field 'int com.google.android.exoplayer2.ExoPlaybackException.type' on a null object reference
        at com.myapp.exoplayer.util.PlayerUtil.isBehindLiveWindow(PlayerUtil.java:88)
        at com.myapp.exoplayer.ExoPlayerActivity$2.onPlayerError(ExoPlayerActivity.java:113)
        at com.google.android.exoplayer2.ExoPlayerImpl.handleEvent(ExoPlayerImpl.java:575)
        at com.google.android.exoplayer2.ExoPlayerImpl$1.handleMessage(ExoPlayerImpl.java:106)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

@andrewlewis
Copy link
Collaborator

Thanks for the information. Each time we notify a listener we access playbackError, but this is set to null if prepare or stop(true) is called, so I think this bug can be triggered if one of those is called from an event listener.

andrewlewis added a commit that referenced this issue May 18, 2018
Issue: #4262

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=197126757
@google google locked and limited conversation to collaborators Sep 27, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants