diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ecf43f8c54..a94511d549 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -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 diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java index 4e612e3acb..8b35a5fc5b 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java @@ -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 schemeDatas) { if (!C.WIDEVINE_UUID.equals(uuid)) { // For non-Widevine CDMs always use the first scheme data.