Skip to content

Commit

Permalink
Check WV version before relying on MediaDrm.requiresSecureDecoder
Browse files Browse the repository at this point in the history
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: #1603

#cherrypick

PiperOrigin-RevId: 662852176
(cherry picked from commit ca455ee)
  • Loading branch information
icbaker authored and tianyif committed Aug 21, 2024
1 parent f139d70 commit b184677
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
6 changes: 6 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
* Image:
* DataSource:
* 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 a `release()` method to `GlObjectsProvider`.
* Muxers:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public Map<String, String> queryKeyStatus(byte[] sessionId) {
@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;
Expand Down Expand Up @@ -408,6 +408,26 @@ private boolean shouldForceAllowInsecureDecoderComponents() {
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.
Expand Down

0 comments on commit b184677

Please sign in to comment.