diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 89685bdce6b..0fef76f7370 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,13 +2,22 @@ ### dev-v2 (not yet released) ### +* DRM: + * Inject `DrmSessionManager` into the `MediaSources` instead of `Renderers` + ([#5619](https://github.com/google/ExoPlayer/issues/5619)). + * Add a `DefaultDrmSessionManager.Builder`. + * Add support for the use of secure decoders in clear sections of content + ([#4867](https://github.com/google/ExoPlayer/issues/4867)). + * Add basic DRM support to the Cast demo app. + * Add support for custom `LoadErrorHandlingPolicies` in key and provisioning + requests ([#6334](https://github.com/google/ExoPlayer/issues/6334)). + * Remove `DefaultDrmSessionManager` factory methods that leak `ExoMediaDrm` + instances ([#4721](https://github.com/google/ExoPlayer/issues/4721)). * Remove the `DataSpec.FLAG_ALLOW_ICY_METADATA` flag. Instead, set the header `IcyHeaders.REQUEST_HEADER_ENABLE_METADATA_NAME` in the `DataSpec` `httpRequestHeaders`. * DASH: Support negative @r values in segment timelines ([#1787](https://github.com/google/ExoPlayer/issues/1787)). -* Remove `DefaultDrmSessionManager` factory methods that leak `ExoMediaDrm` - instances ([#4721](https://github.com/google/ExoPlayer/issues/4721)). * Add `allowedCapturePolicy` field to `AudioAttributes` wrapper to allow to opt-out of audio recording. * Add `DataSpec.httpRequestHeaders` to set HTTP request headers when connecting @@ -24,7 +33,6 @@ display by default. * Add `PlaybackStatsListener` to collect `PlaybackStats` for playbacks analysis and analytics reporting (TODO: link to developer guide page/blog post). -* Add basic DRM support to the Cast demo app. * Assume that encrypted content requires secure decoders in renderer support checks ([#5568](https://github.com/google/ExoPlayer/issues/5568)). * Decoders: Prefer decoders that advertise format support over ones that do not, @@ -50,8 +58,6 @@ the `Player` set later using `AnalyticsCollector.setPlayer`. * Replace `ExoPlayerFactory` by `SimpleExoPlayer.Builder` and `ExoPlayer.Builder`. -* Inject `DrmSessionManager` into the `MediaSources` instead of `Renderers` - ([#5619](https://github.com/google/ExoPlayer/issues/5619)). * Fix issue where player errors are thrown too early at playlist transitions ([#5407](https://github.com/google/ExoPlayer/issues/5407)). * Deprecate `setTag` parameter of `Timeline.getWindow`. Tags will always be set. 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 92cb5d7b8bd..e8a6fe65723 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 @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; /** A {@link DrmSessionManager} that supports playbacks using {@link ExoMediaDrm}. */ @@ -46,6 +47,148 @@ public class DefaultDrmSessionManager implements DrmSessionManager, ProvisioningManager { + /** + * Builder for {@link DefaultDrmSessionManager} instances. + * + *

See {@link #Builder} for the list of default values. + */ + public static final class Builder { + + private final HashMap keyRequestParameters; + private UUID uuid; + private ExoMediaDrm.Provider exoMediaDrmProvider; + private boolean multiSession; + private boolean allowPlaceholderSessions; + @Flags private int flags; + private LoadErrorHandlingPolicy loadErrorHandlingPolicy; + + /** + * Creates a builder with default values. + * + *

    + *
  • {@link #setKeyRequestParameters keyRequestParameters}: An empty map. + *
  • {@link #setUuidAndExoMediaDrmProvider UUID}: {@link C#WIDEVINE_UUID}. + *
  • {@link #setUuidAndExoMediaDrmProvider ExoMediaDrm.Provider}: {@link + * FrameworkMediaDrm#DEFAULT_PROVIDER}. + *
  • {@link #setMultiSession multiSession}: Not allowed by default. + *
  • {@link #setAllowPlaceholderSessions allowPlaceholderSession}: Not allowed by default. + *
  • {@link #setPlayClearSamplesWithoutKeys playClearSamplesWithoutKeys}: Not allowed by + * default. + *
  • {@link #setLoadErrorHandlingPolicy LoadErrorHandlingPolicy}: {@link + * DefaultLoadErrorHandlingPolicy}. + *
+ */ + @SuppressWarnings("unchecked") + public Builder() { + keyRequestParameters = new HashMap<>(); + uuid = C.WIDEVINE_UUID; + exoMediaDrmProvider = (ExoMediaDrm.Provider) FrameworkMediaDrm.DEFAULT_PROVIDER; + multiSession = false; + allowPlaceholderSessions = false; + flags = 0; + loadErrorHandlingPolicy = new DefaultLoadErrorHandlingPolicy(); + } + + /** + * Sets the parameters to pass to {@link ExoMediaDrm#getKeyRequest(byte[], List, int, HashMap)}. + * + * @param keyRequestParameters A map with parameters. + * @return This builder. + */ + public Builder setKeyRequestParameters(Map keyRequestParameters) { + this.keyRequestParameters.clear(); + this.keyRequestParameters.putAll(Assertions.checkNotNull(keyRequestParameters)); + return this; + } + + /** + * Sets the UUID of the DRM scheme and the {@link ExoMediaDrm.Provider} to use. + * + * @param uuid The UUID of the DRM scheme. + * @param exoMediaDrmProvider The {@link ExoMediaDrm.Provider}. + * @return This builder. + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public Builder setUuidAndExoMediaDrmProvider( + UUID uuid, ExoMediaDrm.Provider exoMediaDrmProvider) { + this.uuid = Assertions.checkNotNull(uuid); + this.exoMediaDrmProvider = Assertions.checkNotNull(exoMediaDrmProvider); + return this; + } + + /** + * Sets whether this session manager is allowed to acquire multiple simultaneous sessions. + * + *

Users should pass false when a single key request will obtain all keys required to decrypt + * the associated content. {@code multiSession} is required when content uses key rotation. + * + * @param multiSession Whether this session manager is allowed to acquire multiple simultaneous + * sessions. + * @return This builder. + */ + public Builder setMultiSession(boolean multiSession) { + this.multiSession = multiSession; + return this; + } + + /** + * Sets whether this session manager is allowed to acquire placeholder sessions. + * + *

Placeholder sessions allow the use of secure renderers to play clear content. + * + * @param allowPlaceholderSessions Whether this session manager is allowed to acquire + * placeholder sessions. + * @return This builder. + */ + public Builder setAllowPlaceholderSessions(boolean allowPlaceholderSessions) { + this.allowPlaceholderSessions = allowPlaceholderSessions; + return this; + } + + /** + * Sets whether clear samples should be played when keys are not available. Keys are considered + * unavailable when the load request is taking place, or when the key request has failed. + * + *

This option does not affect placeholder sessions. + * + * @param playClearSamplesWithoutKeys Whether clear samples should be played when keys are not + * available. + * @return This builder. + */ + public Builder setPlayClearSamplesWithoutKeys(boolean playClearSamplesWithoutKeys) { + if (playClearSamplesWithoutKeys) { + this.flags |= FLAG_PLAY_CLEAR_SAMPLES_WITHOUT_KEYS; + } else { + this.flags &= ~FLAG_PLAY_CLEAR_SAMPLES_WITHOUT_KEYS; + } + return this; + } + + /** + * Sets the {@link LoadErrorHandlingPolicy} for key and provisioning requests. + * + * @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}. + * @return This builder. + */ + public Builder setLoadErrorHandlingPolicy(LoadErrorHandlingPolicy loadErrorHandlingPolicy) { + this.loadErrorHandlingPolicy = Assertions.checkNotNull(loadErrorHandlingPolicy); + return this; + } + + /** Builds a {@link DefaultDrmSessionManager} instance. */ + public DefaultDrmSessionManager build(MediaDrmCallback mediaDrmCallback) { + return new DefaultDrmSessionManager<>( + uuid, + exoMediaDrmProvider, + mediaDrmCallback, + keyRequestParameters, + multiSession, + allowPlaceholderSessions, + flags, + loadErrorHandlingPolicy); + } + } + /** * Signals that the {@link DrmInitData} passed to {@link #acquireSession} does not contain does * not contain scheme data for the required UUID. @@ -200,7 +343,6 @@ private DefaultDrmSessionManager( this.optionalKeyRequestParameters = optionalKeyRequestParameters; this.eventDispatcher = new EventDispatcher<>(); this.multiSession = multiSession; - // TODO: Allow customization once this class has a Builder. this.allowPlaceholderSessions = allowPlaceholderSessions; this.flags = flags; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;