google / google/ExoPlayer

Crash in OfflineLicenseHelper

Open
#10,329 2 comments 0 reactions 1 assignee Claimed by @icbaker View on GitHub
bug
Dominant language
Java
Stars
21.9k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

### ExoPlayer Version

2.17.1

### Devices that reproduce the issue

Any. devices.

### Devices that do not reproduce the issue

_No response_

### Reproducible in the demo app?

Yes

### Reproduction steps

1. In _Widevine DASH (MP4, H264)_ -> _HD (cenc)_ in `media.exolist.json`, modify the `drm_license_uri` to `https://proxy.uat.widevine.com/1234567890proxy?video_id=2015_tears&provider=widevine_test` to force to receive 404 not found error.
2. Launch the demo app.
3. Click the download button of _Widevine DASH (MP4, H264)_ -> _HD (cenc)_ in `media.exolist.json`.
4. Do something (play other videos, seek video, download other media...)
5. Repeat step 3 and 4.

> Just call `OfflineLicenseHelper.downloadLicense()` many times at the same time.

### Expected result

offline license failure

### Actual result

The app crashes with an NPE rarely (under 5%).

```
2022-06-10 20:53:52.899 30707-31080/com.google.android.exoplayer2.demo E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #11
Process: com.google.android.exoplayer2.demo, PID: 30707
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:415)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.NullPointerException
at com.google.android.exoplayer2.util.Assertions.checkNotNull(Assertions.java:154)
at com.google.android.exoplayer2.drm.OfflineLicenseHelper.blockingKeyRequest(OfflineLicenseHelper.java:277)
at com.google.android.exoplayer2.drm.OfflineLicenseHelper.downloadLicense(OfflineLicenseHelper.java:193)
at com.google.android.exoplayer2.demo.DownloadTracker$WidevineOfflineLicenseFetchTask.doInBackground(DownloadTracker.java:392)
at com.google.android.exoplayer2.demo.DownloadTracker$WidevineOfflineLicenseFetchTask.doInBackground(DownloadTracker.java:357)
at android.os.AsyncTask$3.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
at java.lang.Thread.run(Thread.java:923) 
```

`DefaultDrmSession.onError()` changes its state after dispatching the error event and `getError()` returns null if the state is not STATE_ERROR.
``` java
public final DrmSessionException getError() {
return state == STATE_ERROR ? lastException : null;
}

private void onError(Exception e, @DrmUtil.ErrorSource int errorSource) {
lastException =
new DrmSessionException(e, DrmUtil.getErrorCodeForMediaDrmException(e, errorSource));
Log.e(TAG, "DRM session error", e);
dispatchEvent(eventDispatcher -> eventDispatcher.drmSessionManagerError(e));
if (state != STATE_OPENED_WITH_KEYS) {
state = STATE_ERROR;
}
}
```
In `OfflineLicenseHelper.blockingKeyRequest()`, both `drmSession.getError()` and `drmSession.getOfflineKeySetId()` returns _null_ at the same time with a low probability.
``` java
DrmSessionException error = drmSession.getError();
byte[] keySetId = drmSession.getOfflineLicenseKeySetId();
// error == null && keySetId == null
```

### Media

_Widevine DASH (MP4, H264)_ -> _HD (cenc)_ , modify the widevine license URL.
(https://proxy.uat.widevine.com/pppppproxy?video_id=2015_tears&provider=widevine_test)

### Bug Report

- [ ] You will email the zip file produced by `adb bugreport` to dev.exoplayer@gmail.com after filing this issue.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.