Commit 603dcf49 by christosts Committed by Oliver Woodman

Download offline DRM license from non-UI thread

PiperOrigin-RevId: 328904901
parent e1c3da2a
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
package com.google.android.exoplayer2.demo; package com.google.android.exoplayer2.demo;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -170,6 +172,7 @@ public class DownloadTracker { ...@@ -170,6 +172,7 @@ public class DownloadTracker {
private TrackSelectionDialog trackSelectionDialog; private TrackSelectionDialog trackSelectionDialog;
private MappedTrackInfo mappedTrackInfo; private MappedTrackInfo mappedTrackInfo;
private WidevineOfflineLicenseFetchTask widevineOfflineLicenseFetchTask;
@Nullable private byte[] keySetId; @Nullable private byte[] keySetId;
public StartDownloadDialogHelper( public StartDownloadDialogHelper(
...@@ -185,6 +188,9 @@ public class DownloadTracker { ...@@ -185,6 +188,9 @@ public class DownloadTracker {
if (trackSelectionDialog != null) { if (trackSelectionDialog != null) {
trackSelectionDialog.dismiss(); trackSelectionDialog.dismiss();
} }
if (widevineOfflineLicenseFetchTask != null) {
widevineOfflineLicenseFetchTask.cancel(false);
}
} }
// DownloadHelper.Callback implementation. // DownloadHelper.Callback implementation.
...@@ -192,59 +198,32 @@ public class DownloadTracker { ...@@ -192,59 +198,32 @@ public class DownloadTracker {
@Override @Override
public void onPrepared(@NonNull DownloadHelper helper) { public void onPrepared(@NonNull DownloadHelper helper) {
@Nullable Format format = getFirstFormatWithDrmInitData(helper); @Nullable Format format = getFirstFormatWithDrmInitData(helper);
if (format != null) { if (format == null) {
if (Util.SDK_INT < 18) { onDownloadPrepared(helper);
Toast.makeText(context, R.string.error_drm_unsupported_before_api_18, Toast.LENGTH_LONG) return;
.show();
Log.e(TAG, "Downloading DRM protected content is not supported on API versions below 18");
return;
}
// TODO(internal b/163107948): Support cases where DrmInitData are not in the manifest.
if (!hasSchemaData(format.drmInitData)) {
Toast.makeText(context, R.string.download_start_error_offline_license, Toast.LENGTH_LONG)
.show();
Log.e(
TAG,
"Downloading content where DRM scheme data is not located in the manifest is not"
+ " supported");
return;
}
try {
// TODO(internal b/163107948): Download the license on another thread to keep the UI
// thread unblocked.
fetchOfflineLicense(format);
} catch (DrmSession.DrmSessionException e) {
Toast.makeText(context, R.string.download_start_error_offline_license, Toast.LENGTH_LONG)
.show();
Log.e(TAG, "Failed to fetch offline DRM license", e);
return;
}
} }
if (helper.getPeriodCount() == 0) { // The content is DRM protected. We need to acquire an offline license.
Log.d(TAG, "No periods found. Downloading entire stream."); if (Util.SDK_INT < 18) {
startDownload(); Toast.makeText(context, R.string.error_drm_unsupported_before_api_18, Toast.LENGTH_LONG)
downloadHelper.release(); .show();
Log.e(TAG, "Downloading DRM protected content is not supported on API versions below 18");
return; return;
} }
// TODO(internal b/163107948): Support cases where DrmInitData are not in the manifest.
mappedTrackInfo = downloadHelper.getMappedTrackInfo(/* periodIndex= */ 0); if (!hasSchemaData(format.drmInitData)) {
if (!TrackSelectionDialog.willHaveContent(mappedTrackInfo)) { Toast.makeText(context, R.string.download_start_error_offline_license, Toast.LENGTH_LONG)
Log.d(TAG, "No dialog content. Downloading entire stream."); .show();
startDownload(); Log.e(
downloadHelper.release(); TAG,
"Downloading content where DRM scheme data is not located in the manifest is not"
+ " supported");
return; return;
} }
trackSelectionDialog = widevineOfflineLicenseFetchTask =
TrackSelectionDialog.createForMappedTrackInfoAndParameters( new WidevineOfflineLicenseFetchTask(
/* titleId= */ R.string.exo_download_description, format, mediaItem.playbackProperties.drmConfiguration.licenseUri, this, helper);
mappedTrackInfo, widevineOfflineLicenseFetchTask.execute();
trackSelectorParameters,
/* allowAdaptiveSelections =*/ false,
/* allowMultipleOverrides= */ true,
/* onClickListener= */ this,
/* onDismissListener= */ this);
trackSelectionDialog.show(fragmentManager, /* tag= */ null);
} }
@Override @Override
...@@ -292,6 +271,44 @@ public class DownloadTracker { ...@@ -292,6 +271,44 @@ public class DownloadTracker {
// Internal methods. // Internal methods.
private void onOfflineLicenseFetched(DownloadHelper helper, byte[] keySetId) {
this.keySetId = keySetId;
onDownloadPrepared(helper);
}
private void onOfflineLicenseFetchedError(DrmSession.DrmSessionException e) {
Toast.makeText(context, R.string.download_start_error_offline_license, Toast.LENGTH_LONG)
.show();
Log.e(TAG, "Failed to fetch offline DRM license", e);
}
private void onDownloadPrepared(DownloadHelper helper) {
if (helper.getPeriodCount() == 0) {
Log.d(TAG, "No periods found. Downloading entire stream.");
startDownload();
downloadHelper.release();
return;
}
mappedTrackInfo = downloadHelper.getMappedTrackInfo(/* periodIndex= */ 0);
if (!TrackSelectionDialog.willHaveContent(mappedTrackInfo)) {
Log.d(TAG, "No dialog content. Downloading entire stream.");
startDownload();
downloadHelper.release();
return;
}
trackSelectionDialog =
TrackSelectionDialog.createForMappedTrackInfoAndParameters(
/* titleId= */ R.string.exo_download_description,
mappedTrackInfo,
trackSelectorParameters,
/* allowAdaptiveSelections =*/ false,
/* allowMultipleOverrides= */ true,
/* onClickListener= */ this,
/* onDismissListener= */ this);
trackSelectionDialog.show(fragmentManager, /* tag= */ null);
}
private void startDownload() { private void startDownload() {
startDownload(buildDownloadRequest()); startDownload(buildDownloadRequest());
} }
...@@ -306,15 +323,54 @@ public class DownloadTracker { ...@@ -306,15 +323,54 @@ public class DownloadTracker {
.getDownloadRequest(Util.getUtf8Bytes(checkNotNull(mediaItem.mediaMetadata.title))) .getDownloadRequest(Util.getUtf8Bytes(checkNotNull(mediaItem.mediaMetadata.title)))
.copyWithKeySetId(keySetId); .copyWithKeySetId(keySetId);
} }
}
@RequiresApi(18) /** Downloads a Widevine offline license in a background thread. */
private void fetchOfflineLicense(Format format) throws DrmSession.DrmSessionException { @RequiresApi(18)
private final class WidevineOfflineLicenseFetchTask extends AsyncTask<Void, Void, Void> {
private final Format format;
private final Uri licenseUri;
private final StartDownloadDialogHelper dialogHelper;
private final DownloadHelper downloadHelper;
@Nullable private byte[] keySetId;
@Nullable private DrmSession.DrmSessionException drmSessionException;
public WidevineOfflineLicenseFetchTask(
Format format,
Uri licenseUri,
StartDownloadDialogHelper dialogHelper,
DownloadHelper downloadHelper) {
this.format = format;
this.licenseUri = licenseUri;
this.dialogHelper = dialogHelper;
this.downloadHelper = downloadHelper;
}
@Override
protected Void doInBackground(Void... voids) {
OfflineLicenseHelper offlineLicenseHelper = OfflineLicenseHelper offlineLicenseHelper =
OfflineLicenseHelper.newWidevineInstance( OfflineLicenseHelper.newWidevineInstance(
mediaItem.playbackProperties.drmConfiguration.licenseUri.toString(), licenseUri.toString(),
httpDataSourceFactory, httpDataSourceFactory,
new DrmSessionEventListener.EventDispatcher()); new DrmSessionEventListener.EventDispatcher());
keySetId = offlineLicenseHelper.downloadLicense(format); try {
keySetId = offlineLicenseHelper.downloadLicense(format);
} catch (DrmSession.DrmSessionException e) {
drmSessionException = e;
} finally {
offlineLicenseHelper.release();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if (drmSessionException != null) {
dialogHelper.onOfflineLicenseFetchedError(drmSessionException);
} else {
dialogHelper.onOfflineLicenseFetched(downloadHelper, checkStateNotNull(keySetId));
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment