Introduce ExoMediaDrm.Provider into DefaultDrmSessionManager

Issue:#4721
PiperOrigin-RevId: 271127127
This commit is contained in:
aquilescanta 2019-09-25 16:18:30 +01:00 committed by Oliver Woodman
parent e4cabcac0f
commit c2bab7a745
2 changed files with 55 additions and 28 deletions

View File

@ -87,7 +87,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
private static final String TAG = "DefaultDrmSessionMgr";
private final UUID uuid;
private final ExoMediaDrm<T> mediaDrm;
private final ExoMediaDrm.Provider<T> exoMediaDrmProvider;
private final MediaDrmCallback callback;
@Nullable private final HashMap<String, String> optionalKeyRequestParameters;
private final EventDispatcher<DefaultDrmSessionEventListener> eventDispatcher;
@ -98,6 +98,8 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
private final List<DefaultDrmSession<T>> sessions;
private final List<DefaultDrmSession<T>> provisioningSessions;
private int prepareCallsCount;
@Nullable private ExoMediaDrm<T> exoMediaDrm;
@Nullable private DefaultDrmSession<T> placeholderDrmSession;
@Nullable private Looper playbackLooper;
private int mode;
@ -107,19 +109,19 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
/**
* @param uuid The UUID of the drm scheme.
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param exoMediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link ExoMediaDrm#getKeyRequest(byte[], List, int, HashMap)}. May be null.
*/
public DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
ExoMediaDrm<T> exoMediaDrm,
MediaDrmCallback callback,
@Nullable HashMap<String, String> optionalKeyRequestParameters) {
this(
uuid,
mediaDrm,
exoMediaDrm,
callback,
optionalKeyRequestParameters,
/* multiSession= */ false,
@ -128,7 +130,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
/**
* @param uuid The UUID of the drm scheme.
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param exoMediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link ExoMediaDrm#getKeyRequest(byte[], List, int, HashMap)}. May be null.
@ -137,13 +139,13 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
*/
public DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
ExoMediaDrm<T> exoMediaDrm,
MediaDrmCallback callback,
@Nullable HashMap<String, String> optionalKeyRequestParameters,
boolean multiSession) {
this(
uuid,
mediaDrm,
exoMediaDrm,
callback,
optionalKeyRequestParameters,
multiSession,
@ -152,7 +154,7 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
/**
* @param uuid The UUID of the drm scheme.
* @param mediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param exoMediaDrm An underlying {@link ExoMediaDrm} for use by the manager.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link ExoMediaDrm#getKeyRequest(byte[], List, int, HashMap)}. May be null.
@ -163,14 +165,14 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
*/
public DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
ExoMediaDrm<T> exoMediaDrm,
MediaDrmCallback callback,
@Nullable HashMap<String, String> optionalKeyRequestParameters,
boolean multiSession,
int initialDrmRequestRetryCount) {
this(
uuid,
mediaDrm,
new ExoMediaDrm.AppManagedProvider<>(exoMediaDrm),
callback,
optionalKeyRequestParameters,
multiSession,
@ -180,38 +182,26 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
private DefaultDrmSessionManager(
UUID uuid,
ExoMediaDrm<T> mediaDrm,
ExoMediaDrm.Provider<T> exoMediaDrmProvider,
MediaDrmCallback callback,
@Nullable HashMap<String, String> optionalKeyRequestParameters,
boolean multiSession,
boolean allowPlaceholderSessions,
LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
Assertions.checkNotNull(uuid);
Assertions.checkNotNull(mediaDrm);
Assertions.checkArgument(!C.COMMON_PSSH_UUID.equals(uuid), "Use C.CLEARKEY_UUID instead");
this.uuid = uuid;
this.mediaDrm = mediaDrm;
this.exoMediaDrmProvider = exoMediaDrmProvider;
this.callback = callback;
this.optionalKeyRequestParameters = optionalKeyRequestParameters;
this.eventDispatcher = new EventDispatcher<>();
this.multiSession = multiSession;
boolean canAcquirePlaceholderSessions =
!FrameworkMediaCrypto.class.equals(mediaDrm.getExoMediaCryptoType())
|| !FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC;
// TODO: Allow customization once this class has a Builder.
this.allowPlaceholderSessions = canAcquirePlaceholderSessions && allowPlaceholderSessions;
this.allowPlaceholderSessions = allowPlaceholderSessions;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
mode = MODE_PLAYBACK;
sessions = new ArrayList<>();
provisioningSessions = new ArrayList<>();
if (multiSession && C.WIDEVINE_UUID.equals(uuid) && Util.SDK_INT >= 19) {
// TODO: Enabling session sharing probably doesn't do anything useful here. It would only be
// useful if DefaultDrmSession instances were aware of one another's state, which is not
// implemented. Or if custom renderers are being used that allow playback to proceed before
// keys, which seems unlikely to be true in practice.
mediaDrm.setPropertyString("sessionSharing", "enable");
}
mediaDrm.setOnEventListener(new MediaDrmEventListener());
}
/**
@ -268,6 +258,30 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
// DrmSessionManager implementation.
@Override
public final void prepare() {
if (prepareCallsCount++ == 0) {
Assertions.checkState(exoMediaDrm == null);
exoMediaDrm = exoMediaDrmProvider.acquireExoMediaDrm(uuid);
if (multiSession && C.WIDEVINE_UUID.equals(uuid) && Util.SDK_INT >= 19) {
// TODO: Enabling session sharing probably doesn't do anything useful here. It would only be
// useful if DefaultDrmSession instances were aware of one another's state, which is not
// implemented. Or if custom renderers are being used that allow playback to proceed before
// keys, which seems unlikely to be true in practice.
exoMediaDrm.setPropertyString("sessionSharing", "enable");
}
exoMediaDrm.setOnEventListener(new MediaDrmEventListener());
}
}
@Override
public final void release() {
if (--prepareCallsCount == 0) {
Assertions.checkNotNull(exoMediaDrm).release();
exoMediaDrm = null;
}
}
@Override
public boolean canAcquireSession(DrmInitData drmInitData) {
if (offlineLicenseKeySetId != null) {
@ -304,7 +318,13 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
@Nullable
public DrmSession<T> acquirePlaceholderSession(Looper playbackLooper) {
assertExpectedPlaybackLooper(playbackLooper);
if (!allowPlaceholderSessions || mediaDrm.getExoMediaCryptoType() == null) {
Assertions.checkNotNull(exoMediaDrm);
boolean avoidPlaceholderDrmSessions =
FrameworkMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType())
&& FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC;
if (avoidPlaceholderDrmSessions
|| !allowPlaceholderSessions
|| exoMediaDrm.getExoMediaCryptoType() == null) {
return null;
}
maybeCreateMediaDrmHandler(playbackLooper);
@ -359,7 +379,9 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
@Override
@Nullable
public Class<T> getExoMediaCryptoType(DrmInitData drmInitData) {
return canAcquireSession(drmInitData) ? mediaDrm.getExoMediaCryptoType() : null;
return canAcquireSession(drmInitData)
? Assertions.checkNotNull(exoMediaDrm).getExoMediaCryptoType()
: null;
}
// ProvisioningManager implementation.
@ -408,9 +430,10 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
private DefaultDrmSession<T> createNewDefaultSession(
@Nullable List<SchemeData> schemeDatas, boolean isPlaceholderSession) {
Assertions.checkNotNull(exoMediaDrm);
return new DefaultDrmSession<>(
uuid,
mediaDrm,
exoMediaDrm,
/* provisioningManager= */ this,
/* releaseCallback= */ this::onSessionReleased,
schemeDatas,

View File

@ -201,6 +201,7 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
public synchronized Pair<Long, Long> getLicenseDurationRemainingSec(byte[] offlineLicenseKeySetId)
throws DrmSessionException {
Assertions.checkNotNull(offlineLicenseKeySetId);
drmSessionManager.prepare();
DrmSession<T> drmSession =
openBlockingKeyRequest(
DefaultDrmSessionManager.MODE_QUERY, offlineLicenseKeySetId, DUMMY_DRM_INIT_DATA);
@ -208,6 +209,7 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
Pair<Long, Long> licenseDurationRemainingSec =
WidevineUtil.getLicenseDurationRemainingSec(drmSession);
drmSession.releaseReference();
drmSessionManager.release();
if (error != null) {
if (error.getCause() instanceof KeysExpiredException) {
return Pair.create(0L, 0L);
@ -227,11 +229,13 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
private byte[] blockingKeyRequest(
@Mode int licenseMode, @Nullable byte[] offlineLicenseKeySetId, DrmInitData drmInitData)
throws DrmSessionException {
drmSessionManager.prepare();
DrmSession<T> drmSession = openBlockingKeyRequest(licenseMode, offlineLicenseKeySetId,
drmInitData);
DrmSessionException error = drmSession.getError();
byte[] keySetId = drmSession.getOfflineLicenseKeySetId();
drmSession.releaseReference();
drmSessionManager.release();
if (error != null) {
throw error;
}