Skip to content

Commit

Permalink
Consolidate requiresSecureDecoder logic in ExoMediaDrm
Browse files Browse the repository at this point in the history
This change:
1. Updates the implementation of
   `FrameworkMediaDrm.requiresSecureDecoder` to include the
   'force allow insecure decoder' workaround logic.
2. Removes the 'force allow insecure decoder' logic from MCR
3. Removes the `requiresSecureDecoder` field from MCR (it can just
   be a local derived from `codecDrmSession` now).

PiperOrigin-RevId: 607664186
  • Loading branch information
icbaker authored and copybara-github committed Feb 16, 2024
1 parent fa3212e commit c872af4
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,18 @@ public final class FrameworkCryptoConfig implements CryptoConfig {
public final byte[] sessionId;

/**
* Whether to allow use of insecure decoder components even if the underlying platform says
* otherwise.
* @deprecated Use {@link ExoMediaDrm#requiresSecureDecoder} instead, which incorporates this
* logic.
*/
public final boolean forceAllowInsecureDecoderComponents;
@Deprecated public final boolean forceAllowInsecureDecoderComponents;

/**
* @param uuid The DRM scheme UUID.
* @param sessionId The DRM session id.
* @param forceAllowInsecureDecoderComponents Whether to allow use of insecure decoder components
* even if the underlying platform says otherwise.
*/
@SuppressWarnings("deprecation") // Setting deprecated field
public FrameworkCryptoConfig(
UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) {
this.uuid = uuid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,22 +287,24 @@ public Map<String, String> queryKeyStatus(byte[] sessionId) {
@UnstableApi
@Override
public boolean requiresSecureDecoder(byte[] sessionId, String mimeType) {
boolean result;
if (Util.SDK_INT >= 31) {
return Api31.requiresSecureDecoder(mediaDrm, mimeType);
}

MediaCrypto mediaCrypto;
try {
mediaCrypto = new MediaCrypto(uuid, sessionId);
} catch (MediaCryptoException e) {
// This shouldn't happen, but if it does then assume that a secure decoder may be required.
return true;
}
try {
return mediaCrypto.requiresSecureDecoderComponent(mimeType);
} finally {
mediaCrypto.release();
result = Api31.requiresSecureDecoder(mediaDrm, mimeType);
} else {
MediaCrypto mediaCrypto = null;
try {
mediaCrypto = new MediaCrypto(uuid, sessionId);
result = mediaCrypto.requiresSecureDecoderComponent(mimeType);
} catch (MediaCryptoException e) {
// This shouldn't happen, but if it does then assume that a secure decoder may be required.
result = true;
} finally {
if (mediaCrypto != null) {
mediaCrypto.release();
}
}
}
return result && !shouldForceAllowInsecureDecoderComponents();
}

@UnstableApi
Expand Down Expand Up @@ -383,16 +385,19 @@ public void setPropertyByteArray(String propertyName, byte[] value) {
@UnstableApi
@Override
public FrameworkCryptoConfig createCryptoConfig(byte[] sessionId) throws MediaCryptoException {
// Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still
// indicate that it required secure video decoders [Internal ref: b/11428937].
boolean forceAllowInsecureDecoderComponents =
Util.SDK_INT < 21
&& C.WIDEVINE_UUID.equals(uuid)
&& "L3".equals(getPropertyString("securityLevel"));
boolean forceAllowInsecureDecoderComponents = shouldForceAllowInsecureDecoderComponents();
return new FrameworkCryptoConfig(
adjustUuid(uuid), sessionId, forceAllowInsecureDecoderComponents);
}

// Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still
// indicate that it required secure video decoders [Internal ref: b/11428937].
private boolean shouldForceAllowInsecureDecoderComponents() {
return Util.SDK_INT < 21
&& C.WIDEVINE_UUID.equals(uuid)
&& "L3".equals(getPropertyString("securityLevel"));
}

@UnstableApi
@Override
public @C.CryptoType int getCryptoType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,6 @@ private static String buildCustomDiagnosticInfo(int errorCode) {
*/
@Nullable private MediaCrypto mediaCrypto;

private boolean mediaCryptoRequiresSecureDecoder;
private long renderTimeLimitMs;
private float currentPlaybackSpeed;
private float targetPlaybackSpeed;
Expand Down Expand Up @@ -539,6 +538,7 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException {
// We have a codec, are bypassing it, or don't have a format to decide how to render.
return;
}
Format inputFormat = this.inputFormat;

if (isBypassPossible(inputFormat)) {
initBypass(inputFormat);
Expand All @@ -548,6 +548,10 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException {
setCodecDrmSession(sourceDrmSession);
if (codecDrmSession == null || initMediaCryptoIfDrmSessionReady()) {
try {
boolean mediaCryptoRequiresSecureDecoder =
codecDrmSession != null
&& codecDrmSession.requiresSecureDecoder(
checkStateNotNull(inputFormat.sampleMimeType));
maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder);
} catch (DecoderInitializationException e) {
throw createRendererException(
Expand All @@ -558,7 +562,6 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException {
// mediaCrypto was created, but a codec wasn't, so release the mediaCrypto before returning.
mediaCrypto.release();
mediaCrypto = null;
mediaCryptoRequiresSecureDecoder = false;
}
}

Expand Down Expand Up @@ -968,7 +971,6 @@ protected void resetCodecStateForRelease() {
codecNeedsEosPropagation = false;
codecReconfigured = false;
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
mediaCryptoRequiresSecureDecoder = false;
}

protected MediaCodecDecoderException createDecoderException(
Expand Down Expand Up @@ -1011,7 +1013,6 @@ private boolean readSourceOmittingSampleData(@SampleStream.ReadFlags int readFla
private boolean initMediaCryptoIfDrmSessionReady() throws ExoPlaybackException {
checkState(mediaCrypto == null);
DrmSession codecDrmSession = this.codecDrmSession;
String mimeType = checkNotNull(inputFormat).sampleMimeType;
@Nullable CryptoConfig cryptoConfig = codecDrmSession.getCryptoConfig();
if (FrameworkCryptoConfig.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC
&& cryptoConfig instanceof FrameworkCryptoConfig) {
Expand Down Expand Up @@ -1044,9 +1045,6 @@ private boolean initMediaCryptoIfDrmSessionReady() throws ExoPlaybackException {
throw createRendererException(
e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR);
}
mediaCryptoRequiresSecureDecoder =
!frameworkCryptoConfig.forceAllowInsecureDecoderComponents
&& mediaCrypto.requiresSecureDecoderComponent(checkStateNotNull(mimeType));
}
return true;
}
Expand Down Expand Up @@ -2228,8 +2226,6 @@ private boolean drmNeedsCodecReinitialization(
return false;
}

FrameworkCryptoConfig newFrameworkCryptoConfig = (FrameworkCryptoConfig) newCryptoConfig;

// Note: Both oldSession and newSession are non-null, and they are different sessions.

if (!newSession.getSchemeUuid().equals(oldSession.getSchemeUuid())) {
Expand All @@ -2250,20 +2246,10 @@ private boolean drmNeedsCodecReinitialization(
return true;
}

boolean requiresSecureDecoder;
if (newFrameworkCryptoConfig.forceAllowInsecureDecoderComponents) {
requiresSecureDecoder = false;
} else {
requiresSecureDecoder =
newSession.requiresSecureDecoder(checkNotNull(newFormat.sampleMimeType));
}
if (!codecInfo.secure && requiresSecureDecoder) {
// Re-initialization is required because newSession might require switching to the secure
// output path.
return true;
}

return false;
// Re-initialization is required if newSession might require switching to the secure output
// path.
return !codecInfo.secure
&& newSession.requiresSecureDecoder(checkNotNull(newFormat.sampleMimeType));
}

private void reinitializeCodec() throws ExoPlaybackException {
Expand Down

0 comments on commit c872af4

Please sign in to comment.