From d2e8b43f6ff511b1488a35ca64f261e860707b5a Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Thu, 21 Nov 2019 20:27:56 -0800 Subject: [PATCH] MediaDrm: enumerate supported schemes Bug: 139134043 Test: MediaDrmTest Change-Id: If6f8c8afb7f96a424556638d6909ff0396f0612e --- api/current.txt | 1 + media/java/android/media/MediaDrm.java | 35 ++++++++++++++++++++++++++ media/jni/Android.bp | 1 + media/jni/android_media_MediaDrm.cpp | 26 ++++++++++++++++++- 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/api/current.txt b/api/current.txt index f1c03a4e576d3..5ae43bcdfd363 100644 --- a/api/current.txt +++ b/api/current.txt @@ -25048,6 +25048,7 @@ package android.media { method @NonNull public java.util.List getSecureStopIds(); method @NonNull public java.util.List getSecureStops(); method @android.media.MediaDrm.SecurityLevel public int getSecurityLevel(@NonNull byte[]); + method @NonNull public static java.util.List getSupportedCryptoSchemes(); method public static boolean isCryptoSchemeSupported(@NonNull java.util.UUID); method public static boolean isCryptoSchemeSupported(@NonNull java.util.UUID, @NonNull String); method public static boolean isCryptoSchemeSupported(@NonNull java.util.UUID, @NonNull String, @android.media.MediaDrm.SecurityLevel int); diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index 63657a6c4a5c1..6523e30c13cc5 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -36,9 +36,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; @@ -203,6 +206,16 @@ public final class MediaDrm implements AutoCloseable { securityLevel); } + /** + * @return list of crypto schemes (as {@link UUID}s) for which + * {@link #isCryptoSchemeSupported(UUID)} returns true; each {@link UUID} + * can be used as input to create {@link MediaDrm} objects via {@link #MediaDrm(UUID)}. + */ + public static final @NonNull List getSupportedCryptoSchemes(){ + byte[] uuidBytes = getSupportedCryptoSchemesNative(); + return getUUIDsFromByteArray(uuidBytes); + } + private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) { long msb = uuid.getMostSignificantBits(); long lsb = uuid.getLeastSignificantBits(); @@ -216,6 +229,28 @@ public final class MediaDrm implements AutoCloseable { return uuidBytes; } + private static final UUID getUUIDFromByteArray(@NonNull byte[] uuidBytes, int off) { + long msb = 0; + long lsb = 0; + + for (int i = 0; i < 8; ++i) { + msb = (msb << 8) | (0xffl & uuidBytes[off + i]); + lsb = (lsb << 8) | (0xffl & uuidBytes[off + i + 8]); + } + + return new UUID(msb, lsb); + } + + private static final List getUUIDsFromByteArray(@NonNull byte[] uuidBytes) { + Set uuids = new LinkedHashSet<>(); + for (int off = 0; off < uuidBytes.length; off+=16) { + uuids.add(getUUIDFromByteArray(uuidBytes, off)); + } + return new ArrayList<>(uuids); + } + + private static final native byte[] getSupportedCryptoSchemesNative(); + private static final native boolean isCryptoSchemeSupportedNative( @NonNull byte[] uuid, @Nullable String mimeType, @SecurityLevel int securityLevel); diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 2f53cbb24129a..3ba868835151d 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -58,6 +58,7 @@ cc_library_shared { "libsonivox", "android.hardware.cas@1.0", "android.hardware.cas.native@1.0", + "android.hardware.drm@1.3", "android.hidl.memory@1.0", "android.hidl.token@1.0-utils", ], diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp index 3833c6bfb6764..ee6bbf467e845 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -27,6 +27,7 @@ #include "jni.h" #include +#include #include #include #include @@ -36,7 +37,7 @@ #include using ::android::os::PersistableBundle; - +namespace drm = ::android::hardware::drm; namespace android { @@ -969,6 +970,26 @@ DrmPlugin::SecurityLevel jintToSecurityLevel(jint jlevel) { return level; } +static jbyteArray android_media_MediaDrm_getSupportedCryptoSchemesNative(JNIEnv *env) { + std::vector bv; + for (auto &factory : DrmUtils::MakeDrmFactories()) { + sp factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory); + if (factoryV1_3 == nullptr) { + continue; + } + factoryV1_3->getSupportedCryptoSchemes( + [&](const hardware::hidl_vec>& schemes) { + for (const auto &scheme : schemes) { + bv.insert(bv.end(), scheme.data(), scheme.data() + scheme.size()); + } + }); + } + + jbyteArray jUuidBytes = env->NewByteArray(bv.size()); + env->SetByteArrayRegion(jUuidBytes, 0, bv.size(), reinterpret_cast(bv.data())); + return jUuidBytes; +} + static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative( JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType, jint jSecurityLevel) { @@ -1938,6 +1959,9 @@ static const JNINativeMethod gMethods[] = { { "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V", (void *)android_media_MediaDrm_native_setup }, + { "getSupportedCryptoSchemesNative", "()[B", + (void *)android_media_MediaDrm_getSupportedCryptoSchemesNative }, + { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;I)Z", (void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },