diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6e726ee8ef..59c32b9927 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -80,6 +80,9 @@ * Remove `DrmSessionManager` references from all renderers. `DrmSessionManager` must be injected into the MediaSources using the MediaSources factories. + * Add option to inject a custom `DefaultDrmSessionManager` into + `OfflineLicenseHelper` + ([#7078](https://github.com/google/ExoPlayer/issues/7078)). * Downloads: Merge downloads in `SegmentDownloader` to improve overall download speed ([#5978](https://github.com/google/ExoPlayer/issues/5978)). * DASH: diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java index 2b9f2c654f..bcf84479df 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java @@ -88,16 +88,19 @@ public class DefaultDrmSessionManager implements DrmSe /** * Sets the key request parameters to pass as the last argument to {@link - * ExoMediaDrm#getKeyRequest(byte[], List, int, HashMap)}. + * ExoMediaDrm#getKeyRequest(byte[], List, int, HashMap)}. May be null if not parameters need to + * be passed. * *

Custom data for PlayReady should be set under {@link #PLAYREADY_CUSTOM_DATA_KEY}. * * @param keyRequestParameters A map with parameters. * @return This builder. */ - public Builder setKeyRequestParameters(Map keyRequestParameters) { + public Builder setKeyRequestParameters(@Nullable Map keyRequestParameters) { this.keyRequestParameters.clear(); - this.keyRequestParameters.putAll(Assertions.checkNotNull(keyRequestParameters)); + if (keyRequestParameters != null) { + this.keyRequestParameters.putAll(keyRequestParameters); + } return this; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java index cd64788e37..c483bf44c7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java @@ -22,13 +22,11 @@ import android.os.HandlerThread; import android.util.Pair; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager.Mode; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.MediaSourceEventDispatcher; -import java.util.Collections; import java.util.Map; import java.util.UUID; @@ -53,15 +51,16 @@ public final class OfflineLicenseHelper { * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * events. * @return A new instance which uses Widevine CDM. - * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be - * instantiated. */ - public static OfflineLicenseHelper newWidevineInstance( + public static OfflineLicenseHelper newWidevineInstance( String defaultLicenseUrl, HttpDataSource.Factory httpDataSourceFactory, - MediaSourceEventDispatcher eventDispatcher) - throws UnsupportedDrmException { - return newWidevineInstance(defaultLicenseUrl, false, httpDataSourceFactory, eventDispatcher); + MediaSourceEventDispatcher eventDispatcher) { + return newWidevineInstance( + defaultLicenseUrl, + /* forceDefaultLicenseUrl= */ false, + httpDataSourceFactory, + eventDispatcher); } /** @@ -76,15 +75,12 @@ public final class OfflineLicenseHelper { * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * events. * @return A new instance which uses Widevine CDM. - * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be - * instantiated. */ - public static OfflineLicenseHelper newWidevineInstance( + public static OfflineLicenseHelper newWidevineInstance( String defaultLicenseUrl, boolean forceDefaultLicenseUrl, HttpDataSource.Factory httpDataSourceFactory, - MediaSourceEventDispatcher eventDispatcher) - throws UnsupportedDrmException { + MediaSourceEventDispatcher eventDispatcher) { return newWidevineInstance( defaultLicenseUrl, forceDefaultLicenseUrl, @@ -106,37 +102,29 @@ public final class OfflineLicenseHelper { * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * events. * @return A new instance which uses Widevine CDM. - * @throws UnsupportedDrmException If the Widevine DRM scheme is unsupported or cannot be - * instantiated. * @see DefaultDrmSessionManager.Builder */ - public static OfflineLicenseHelper newWidevineInstance( + @SuppressWarnings("unchecked") + public static OfflineLicenseHelper newWidevineInstance( String defaultLicenseUrl, boolean forceDefaultLicenseUrl, HttpDataSource.Factory httpDataSourceFactory, @Nullable Map optionalKeyRequestParameters, - MediaSourceEventDispatcher eventDispatcher) - throws UnsupportedDrmException { + MediaSourceEventDispatcher eventDispatcher) { return new OfflineLicenseHelper<>( - C.WIDEVINE_UUID, - FrameworkMediaDrm.DEFAULT_PROVIDER, - new HttpMediaDrmCallback(defaultLicenseUrl, forceDefaultLicenseUrl, httpDataSourceFactory), - optionalKeyRequestParameters, + new DefaultDrmSessionManager.Builder() + .setKeyRequestParameters(optionalKeyRequestParameters) + .build( + new HttpMediaDrmCallback( + defaultLicenseUrl, forceDefaultLicenseUrl, httpDataSourceFactory)), eventDispatcher); } /** - * Constructs an instance. Call {@link #release()} when the instance is no longer required. - * - * @param uuid The UUID of the drm scheme. - * @param mediaDrmProvider A {@link ExoMediaDrm.Provider}. - * @param callback Performs key and provisioning requests. - * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument - * to {@link MediaDrm#getKeyRequest}. May be null. - * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related - * events. - * @see DefaultDrmSessionManager.Builder + * @deprecated Use {@link #OfflineLicenseHelper(DefaultDrmSessionManager, + * MediaSourceEventDispatcher)} instead. */ + @Deprecated @SuppressWarnings("unchecked") public OfflineLicenseHelper( UUID uuid, @@ -144,6 +132,27 @@ public final class OfflineLicenseHelper { MediaDrmCallback callback, @Nullable Map optionalKeyRequestParameters, MediaSourceEventDispatcher eventDispatcher) { + this( + (DefaultDrmSessionManager) + new DefaultDrmSessionManager.Builder() + .setUuidAndExoMediaDrmProvider(uuid, mediaDrmProvider) + .setKeyRequestParameters(optionalKeyRequestParameters) + .build(callback), + eventDispatcher); + } + + /** + * Constructs an instance. Call {@link #release()} when the instance is no longer required. + * + * @param defaultDrmSessionManager The {@link DefaultDrmSessionManager} used to download licenses. + * @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related + * events. + */ + public OfflineLicenseHelper( + DefaultDrmSessionManager defaultDrmSessionManager, + MediaSourceEventDispatcher eventDispatcher) { + this.drmSessionManager = defaultDrmSessionManager; + this.eventDispatcher = eventDispatcher; handlerThread = new HandlerThread("OfflineLicenseHelper"); handlerThread.start(); conditionVariable = new ConditionVariable(); @@ -169,17 +178,7 @@ public final class OfflineLicenseHelper { conditionVariable.open(); } }; - if (optionalKeyRequestParameters == null) { - optionalKeyRequestParameters = Collections.emptyMap(); - } - drmSessionManager = - (DefaultDrmSessionManager) - new DefaultDrmSessionManager.Builder() - .setUuidAndExoMediaDrmProvider(uuid, mediaDrmProvider) - .setKeyRequestParameters(optionalKeyRequestParameters) - .build(callback); drmSessionManager.addListener(new Handler(handlerThread.getLooper()), eventListener); - this.eventDispatcher = eventDispatcher; } /** diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java index c049de4ae8..286a84bd37 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/DashWidevineOfflineTest.java @@ -27,7 +27,7 @@ import androidx.test.rule.ActivityTestRule; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; -import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; +import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.OfflineLicenseHelper; import com.google.android.exoplayer2.source.dash.DashUtil; import com.google.android.exoplayer2.source.dash.manifest.DashManifest; @@ -54,7 +54,7 @@ public final class DashWidevineOfflineTest { private DashTestRunner testRunner; private DefaultHttpDataSourceFactory httpDataSourceFactory; - private OfflineLicenseHelper offlineLicenseHelper; + private OfflineLicenseHelper offlineLicenseHelper; private byte[] offlineLicenseKeySetId; @Rule public ActivityTestRule testRule = new ActivityTestRule<>(HostActivity.class); @@ -69,6 +69,7 @@ public final class DashWidevineOfflineTest { .setFullPlaybackNoSeeking(true) .setCanIncludeAdditionalVideoFormats(false) .setAudioVideoFormats( + DashTestData.WIDEVINE_AAC_AUDIO_REPRESENTATION_ID, DashTestData.WIDEVINE_H264_CDD_FIXED);