Check WV version before relying on MediaDrm.requiresSecureDecoder

This method was added in API 31 (S) but it's non-functional
(incorrectly, silently, returns `false`) on the Widevine plugin version
(`16.0`) from R (API 30), which some devices up to at least API 34 are
still using.

This results in ExoPlayer incorrectly selecting an insecure decoder for
L1 secure content, and subsequently calling
`MediaCodec.queueInputBuffer` instead of `queueSecureInputBuffer`,
which is not supported and generates the following error:
> Operation not supported in this configuration: ERROR_DRM_CANNOT_HANDLE

Issue: androidx/media#1603

#cherrypick

PiperOrigin-RevId: 662852176
This commit is contained in:
ibaker 2024-08-14 03:24:51 -07:00 committed by Copybara-Service
parent e7f037bff5
commit ca455ee858
2 changed files with 27 additions and 1 deletions

View File

@ -78,6 +78,12 @@
read from a `FileDescriptor`
([#3757](https://github.com/google/ExoPlayer/issues/3757)).
* DRM:
* Fix `android.media.MediaCodec$CryptoException: Operation not supported
in this configuration: ERROR_DRM_CANNOT_HANDLE` error on API 31+ devices
playing L1 Widevine content. This error is caused by an incomplete
implementation of the framework
[`MediaDrm.requiresSecureDecoder`](https://developer.android.com/reference/android/media/MediaDrm#requiresSecureDecoder\(java.lang.String\))
method ([#1603](https://github.com/google/ExoPlayer/issues/1603)).
* Effect:
* Add `DefaultVideoFrameProcessor` workaround for minor `SurfaceTexture`
scaling. `SurfaceTexture` may include a small scaling that cuts off a

View File

@ -292,7 +292,7 @@ public final class FrameworkMediaDrm implements ExoMediaDrm {
@Override
public boolean requiresSecureDecoder(byte[] sessionId, String mimeType) {
boolean result;
if (Util.SDK_INT >= 31) {
if (Util.SDK_INT >= 31 && isMediaDrmRequiresSecureDecoderImplemented()) {
result = Api31.requiresSecureDecoder(mediaDrm, mimeType);
} else {
MediaCrypto mediaCrypto = null;
@ -398,6 +398,26 @@ public final class FrameworkMediaDrm implements ExoMediaDrm {
return C.CRYPTO_TYPE_FRAMEWORK;
}
/**
* {@link MediaDrm#requiresSecureDecoder} is nominally available from API 31, but it's only
* functional for Widevine if the plugin version is greater than 16.0. See b/352419654#comment63.
*/
@RequiresApi(31)
private boolean isMediaDrmRequiresSecureDecoderImplemented() {
// TODO: b/359768062 - Add an SDK_INT guard clause once WV 16.0 is not permitted on any device.
if (uuid.equals(C.WIDEVINE_UUID)) {
String pluginVersion = getPropertyString(MediaDrm.PROPERTY_VERSION);
return !pluginVersion.startsWith("v5.")
&& !pluginVersion.startsWith("14.")
&& !pluginVersion.startsWith("15.")
&& !pluginVersion.startsWith("16.0");
} else {
// Assume that ClearKey plugin always supports this method, and no non-Google plugin does. See
// b/352419654#comment71.
return uuid.equals(C.CLEARKEY_UUID);
}
}
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {
if (!C.WIDEVINE_UUID.equals(uuid)) {
// For non-Widevine CDMs always use the first scheme data.