Loading drm/aidl/vts/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ cc_test { "android.hardware.drm@1.0-helper", "android.hardware.drm-V1-ndk", "android.hardware.common-V2-ndk", "libaidlcommonsupport", "libgmock_ndk", "libdrmvtshelper", "libvtsclearkey", ], Loading drm/aidl/vts/drm_hal_common.cpp +75 −50 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ #include <sys/mman.h> #include <random> #include <aidlcommonsupport/NativeHandle.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <android/sharedmem.h> #include <cutils/native_handle.h> #include "drm_hal_clearkey_module.h" #include "drm_hal_common.h" Loading @@ -39,8 +41,7 @@ namespace clearkeydrm = ::android::hardware::drm::V1_2::vts; using std::vector; using ::aidl::android::hardware::common::Ashmem; using ::aidl::android::hardware::drm::BufferType; using ::aidl::android::hardware::drm::DecryptResult; using ::aidl::android::hardware::drm::DecryptArgs; using ::aidl::android::hardware::drm::DestinationBuffer; using ::aidl::android::hardware::drm::EventType; using ::aidl::android::hardware::drm::ICryptoPlugin; Loading Loading @@ -72,7 +73,6 @@ std::string HalBaseName(const std::string& fullname) { } const char* kDrmIface = "android.hardware.drm.IDrmFactory"; const char* kCryptoIface = "android.hardware.drm.ICryptoFactory"; std::string HalFullName(const std::string& iface, const std::string& basename) { return iface + '/' + basename; Loading Loading @@ -184,7 +184,6 @@ void DrmHalTest::SetUp() { test_info->name(), GetParamService().c_str()); auto svc = GetParamService(); const string cryptoInstance = HalFullName(kCryptoIface, svc); const string drmInstance = HalFullName(kDrmIface, svc); if (drmInstance.find("IDrmFactory") != std::string::npos) { Loading @@ -192,12 +191,6 @@ void DrmHalTest::SetUp() { ::ndk::SpAIBinder(AServiceManager_waitForService(drmInstance.c_str()))); ASSERT_NE(drmFactory, nullptr); drmPlugin = createDrmPlugin(); } if (cryptoInstance.find("ICryptoFactory") != std::string::npos) { cryptoFactory = ICryptoFactory::fromBinder( ::ndk::SpAIBinder(AServiceManager_waitForService(cryptoInstance.c_str()))); ASSERT_NE(cryptoFactory, nullptr); cryptoPlugin = createCryptoPlugin(); } Loading @@ -211,14 +204,12 @@ void DrmHalTest::SetUp() { contentConfigurations = vendorModule->getContentConfigurations(); // If drm scheme not installed skip subsequent tests bool result = false; drmFactory->isCryptoSchemeSupported({getUUID()}, "cenc", SecurityLevel::SW_SECURE_CRYPTO, &result); bool result = isCryptoSchemeSupported(getAidlUUID(), SecurityLevel::SW_SECURE_CRYPTO, "cenc"); if (!result) { if (GetParamUUID() == std::array<uint8_t, 16>()) { GTEST_SKIP() << "vendor module drm scheme not supported"; } else { FAIL() << "param scheme must not supported"; FAIL() << "param scheme must be supported"; } } Loading @@ -234,18 +225,18 @@ std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin> DrmHalTest::createDr } std::string packageName("aidl.android.hardware.drm.test"); std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin> result; auto ret = drmFactory->createPlugin({getUUID()}, packageName, &result); auto ret = drmFactory->createDrmPlugin(getAidlUUID(), packageName, &result); EXPECT_OK(ret) << "createDrmPlugin remote call failed"; return result; } std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin> DrmHalTest::createCryptoPlugin() { if (cryptoFactory == nullptr) { if (drmFactory == nullptr) { return nullptr; } vector<uint8_t> initVec; std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin> result; auto ret = cryptoFactory->createPlugin({getUUID()}, initVec, &result); auto ret = drmFactory->createCryptoPlugin(getAidlUUID(), initVec, &result); EXPECT_OK(ret) << "createCryptoPlugin remote call failed"; return result; } Loading @@ -270,6 +261,26 @@ std::vector<uint8_t> DrmHalTest::getVendorUUID() { return vendorModule->getUUID(); } bool DrmHalTest::isCryptoSchemeSupported(Uuid uuid, SecurityLevel level, std::string mime) { CryptoSchemes schemes{}; auto ret = drmFactory->getSupportedCryptoSchemes(&schemes); EXPECT_OK(ret); if (!ret.isOk() || !std::count(schemes.uuids.begin(), schemes.uuids.end(), uuid)) { return false; } if (level > schemes.maxLevel || level < schemes.minLevel) { if (level != SecurityLevel::DEFAULT && level != SecurityLevel::UNKNOWN) { return false; } } if (!mime.empty()) { if (!std::count(schemes.mimeTypes.begin(), schemes.mimeTypes.end(), mime)) { return false; } } return true; } void DrmHalTest::provision() { std::string certificateType; std::string certificateAuthority; Loading Loading @@ -410,38 +421,43 @@ KeyedVector DrmHalTest::toAidlKeyedVector(const map<string, string>& params) { /** * getDecryptMemory allocates memory for decryption, then sets it * as a shared buffer base in the crypto hal. A parcelable Ashmem * is returned. * as a shared buffer base in the crypto hal. An output SharedBuffer * is updated via reference. * * @param size the size of the memory segment to allocate * @param the index of the memory segment which will be used * to refer to it for decryption. */ Ashmem DrmHalTest::getDecryptMemory(size_t size, size_t index) { void DrmHalTest::getDecryptMemory(size_t size, size_t index, SharedBuffer& out) { out.bufferId = static_cast<int32_t>(index); out.offset = 0; out.size = static_cast<int64_t>(size); int fd = ASharedMemory_create("drmVtsSharedMemory", size); EXPECT_GE(fd, 0); EXPECT_EQ(size, ASharedMemory_getSize(fd)); auto handle = native_handle_create(1, 0); handle->data[0] = fd; out.handle = ::android::makeToAidl(handle); Ashmem ashmem; ashmem.fd = ::ndk::ScopedFileDescriptor(fd); ashmem.size = size; EXPECT_OK(cryptoPlugin->setSharedBufferBase(ashmem, index)); return ashmem; EXPECT_OK(cryptoPlugin->setSharedBufferBase(out)); native_handle_delete(handle); } void DrmHalTest::fillRandom(const Ashmem& ashmem) { uint8_t* DrmHalTest::fillRandom(const ::aidl::android::hardware::drm::SharedBuffer& buf) { std::random_device rd; std::mt19937 rand(rd()); ::ndk::ScopedFileDescriptor fd = ashmem.fd.dup(); size_t size = ashmem.size; auto fd = buf.handle.fds[0].get(); size_t size = buf.size; uint8_t* base = static_cast<uint8_t*>( mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)); mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); EXPECT_NE(MAP_FAILED, base); for (size_t i = 0; i < size / sizeof(uint32_t); i++) { auto p = static_cast<uint32_t*>(static_cast<void*>(base)); p[i] = rand(); } return base; } uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, 16>& keyId, Loading @@ -453,6 +469,7 @@ uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, uint8_t localIv[AES_BLOCK_SIZE]; memcpy(localIv, iv, AES_BLOCK_SIZE); vector<uint8_t> ivVec(localIv, localIv + AES_BLOCK_SIZE); vector<uint8_t> keyIdVec(keyId.begin(), keyId.end()); int64_t totalSize = 0; for (size_t i = 0; i < subSamples.size(); i++) { Loading @@ -463,32 +480,39 @@ uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, // The first totalSize bytes of shared memory is the encrypted // input, the second totalSize bytes (if exists) is the decrypted output. size_t factor = expectedStatus == Status::ERROR_DRM_FRAME_TOO_LARGE ? 1 : 2; Ashmem sharedMemory = getDecryptMemory(totalSize * factor, kSegmentIndex); const SharedBuffer sourceBuffer = {.bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; fillRandom(sharedMemory); const DestinationBuffer destBuffer = { .type = BufferType::SHARED_MEMORY, .nonsecureMemory = {.bufferId = kSegmentIndex, .offset = totalSize, .size = totalSize}, .secureMemory = {.fds = {}, .ints = {}}}; const uint64_t offset = 0; uint32_t bytesWritten = 0; vector<uint8_t> keyIdVec(keyId.begin(), keyId.end()); DecryptResult result; auto ret = cryptoPlugin->decrypt(isSecure, keyIdVec, ivVec, mode, pattern, subSamples, sourceBuffer, offset, destBuffer, &result); SharedBuffer sourceBuffer; getDecryptMemory(totalSize * factor, kSegmentIndex, sourceBuffer); auto base = fillRandom(sourceBuffer); SharedBuffer sourceRange; sourceRange.bufferId = kSegmentIndex; sourceRange.offset = 0; sourceRange.size = totalSize; SharedBuffer destRange; destRange.bufferId = kSegmentIndex; destRange.offset = totalSize; destRange.size = totalSize; DecryptArgs args; args.secure = isSecure; args.keyId = keyIdVec; args.iv = ivVec; args.mode = mode; args.pattern = pattern; args.subSamples = subSamples; args.source = std::move(sourceRange); args.offset = 0; args.destination = std::move(destRange); int32_t bytesWritten = 0; auto ret = cryptoPlugin->decrypt(args, &bytesWritten); EXPECT_TXN(ret); EXPECT_EQ(expectedStatus, DrmErr(ret)) << "Unexpected decrypt status " << result.detailedError; bytesWritten = result.bytesWritten; EXPECT_EQ(expectedStatus, DrmErr(ret)) << "Unexpected decrypt status " << ret.getMessage(); if (bytesWritten != totalSize) { return bytesWritten; } ::ndk::ScopedFileDescriptor fd = sharedMemory.fd.dup(); uint8_t* base = static_cast<uint8_t*>( mmap(nullptr, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)); EXPECT_NE(MAP_FAILED, base); // generate reference vector vector<uint8_t> reference(totalSize); Loading @@ -513,6 +537,7 @@ uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]), static_cast<void*>(base + totalSize), totalSize)) << "decrypt data mismatch"; munmap(base, totalSize * factor); return totalSize; } Loading drm/aidl/vts/drm_hal_test.cpp +7 −21 Original line number Diff line number Diff line Loading @@ -66,11 +66,8 @@ static constexpr SecurityLevel kHwSecureAll = SecurityLevel::HW_SECURE_ALL; * Ensure drm factory supports module UUID Scheme */ TEST_P(DrmHalTest, VendorUuidSupported) { bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(getAidlUUID(), kVideoMp4, kSwSecureCrypto, &result); ALOGI("kVideoMp4 = %s res %d", kVideoMp4, static_cast<bool>(result)); EXPECT_OK(ret); bool result = isCryptoSchemeSupported(getAidlUUID(), kSwSecureCrypto, kVideoMp4); ALOGI("kVideoMp4 = %s res %d", kVideoMp4, result); EXPECT_TRUE(result); } Loading @@ -80,10 +77,7 @@ TEST_P(DrmHalTest, VendorUuidSupported) { TEST_P(DrmHalTest, InvalidPluginNotSupported) { const vector<uint8_t> kInvalidUUID = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80}; bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(toAidlUuid(kInvalidUUID), kVideoMp4, kSwSecureCrypto, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(toAidlUuid(kInvalidUUID), kSwSecureCrypto, kVideoMp4); EXPECT_FALSE(result); } Loading @@ -93,10 +87,7 @@ TEST_P(DrmHalTest, InvalidPluginNotSupported) { TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) { vector<uint8_t> emptyUUID(16); memset(emptyUUID.data(), 0, 16); bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(toAidlUuid(emptyUUID), kVideoMp4, kSwSecureCrypto, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(toAidlUuid(emptyUUID), kSwSecureCrypto, kVideoMp4); EXPECT_FALSE(result); } Loading @@ -104,10 +95,7 @@ TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) { * Ensure drm factory doesn't support an invalid mime type */ TEST_P(DrmHalTest, BadMimeNotSupported) { bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(getAidlUUID(), kBadMime, kSwSecureCrypto, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(getAidlUUID(), kSwSecureCrypto, kBadMime); EXPECT_FALSE(result); } Loading Loading @@ -380,9 +368,7 @@ TEST_P(DrmHalTest, EncryptedAesCtrSegmentTestNoKeys) { * Ensure clearkey drm factory doesn't support security level higher than supported */ TEST_P(DrmHalClearkeyTest, BadLevelNotSupported) { bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(getAidlUUID(), kVideoMp4, kHwSecureAll, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(getAidlUUID(), kHwSecureAll, kVideoMp4); EXPECT_FALSE(result); } Loading Loading @@ -461,7 +447,7 @@ TEST_P(DrmHalClearkeyTest, ListenerCallbacks) { const vector<KeyStatus> keyStatusList = { {{0xa, 0xb, 0xc}, KeyStatusType::USABLE}, {{0xd, 0xe, 0xf}, KeyStatusType::EXPIRED}, {{0x0, 0x1, 0x2}, KeyStatusType::USABLEINFUTURE}, {{0x0, 0x1, 0x2}, KeyStatusType::USABLE_IN_FUTURE}, }; EXPECT_EQ(sessionId, args.sessionId); EXPECT_EQ(keyStatusList, args.keyStatusList); Loading drm/aidl/vts/drm_hal_test_main.cpp +0 −6 Original line number Diff line number Diff line Loading @@ -42,21 +42,15 @@ using drm_vts::DrmHalTestParam; using drm_vts::PrintParamInstanceToString; static const std::vector<DrmHalTestParam> getAllInstances() { using ::aidl::android::hardware::drm::ICryptoFactory; using ::aidl::android::hardware::drm::IDrmFactory; std::vector<std::string> drmInstances = android::getAidlHalInstanceNames(IDrmFactory::descriptor); std::vector<std::string> cryptoInstances = android::getAidlHalInstanceNames(ICryptoFactory::descriptor); std::set<std::string> allInstances; for (auto svc : drmInstances) { allInstances.insert(HalBaseName(svc)); } for (auto svc : cryptoInstances) { allInstances.insert(HalBaseName(svc)); } std::vector<DrmHalTestParam> allInstanceUuidCombos; auto noUUID = [](std::string s) { return DrmHalTestParam(s); }; Loading drm/aidl/vts/include/drm_hal_common.h +15 −15 Original line number Diff line number Diff line Loading @@ -18,14 +18,17 @@ #include <aidl/android/hardware/common/Ashmem.h> #include <aidl/android/hardware/drm/BnDrmPluginListener.h> #include <aidl/android/hardware/drm/ICryptoFactory.h> #include <aidl/android/hardware/drm/ICryptoPlugin.h> #include <aidl/android/hardware/drm/IDrmFactory.h> #include <aidl/android/hardware/drm/IDrmPlugin.h> #include <aidl/android/hardware/drm/IDrmPluginListener.h> #include <aidl/android/hardware/drm/Status.h> #include <android/binder_auto_utils.h> #include <gmock/gmock.h> #include <array> #include <algorithm> #include <chrono> #include <future> #include <iostream> Loading @@ -35,8 +38,6 @@ #include <utility> #include <vector> #include <android/binder_auto_utils.h> #include "VtsHalHidlTargetCallbackBase.h" #include "drm_hal_vendor_module_api.h" #include "drm_vts_helper.h" Loading Loading @@ -80,11 +81,14 @@ class DrmHalTest : public ::testing::TestWithParam<DrmHalTestParam> { std::array<uint8_t, 16> GetParamUUID() { return GetParam().scheme_; } std::string GetParamService() { return GetParam().instance_; } ::aidl::android::hardware::drm::Uuid toAidlUuid(const std::vector<uint8_t>& in_uuid) { ::aidl::android::hardware::drm::Uuid uuid; uuid.uuid = in_uuid; return uuid; std::array<uint8_t, 16> a; std::copy_n(in_uuid.begin(), a.size(), a.begin()); return {a}; } bool isCryptoSchemeSupported(::aidl::android::hardware::drm::Uuid uuid, ::aidl::android::hardware::drm::SecurityLevel level, std::string mime); void provision(); SessionId openSession(::aidl::android::hardware::drm::SecurityLevel level, ::aidl::android::hardware::drm::Status* err); Loading @@ -106,8 +110,8 @@ class DrmHalTest : public ::testing::TestWithParam<DrmHalTestParam> { KeyedVector toAidlKeyedVector(const std::map<std::string, std::string>& params); std::array<uint8_t, 16> toStdArray(const std::vector<uint8_t>& vec); void fillRandom(const ::aidl::android::hardware::common::Ashmem& ashmem); ::aidl::android::hardware::common::Ashmem getDecryptMemory(size_t size, size_t index); uint8_t* fillRandom(const ::aidl::android::hardware::drm::SharedBuffer& buf); void getDecryptMemory(size_t size, size_t index, SharedBuffer& buf); uint32_t decrypt(::aidl::android::hardware::drm::Mode mode, bool isSecure, const std::array<uint8_t, 16>& keyId, uint8_t* iv, Loading @@ -123,7 +127,6 @@ class DrmHalTest : public ::testing::TestWithParam<DrmHalTestParam> { const std::vector<uint8_t>& key); std::shared_ptr<::aidl::android::hardware::drm::IDrmFactory> drmFactory; std::shared_ptr<::aidl::android::hardware::drm::ICryptoFactory> cryptoFactory; std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin> drmPlugin; std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin> cryptoPlugin; Loading @@ -139,16 +142,13 @@ class DrmHalClearkeyTest : public DrmHalTest { public: virtual void SetUp() override { DrmHalTest::SetUp(); const std::vector<uint8_t> kClearKeyUUID = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E}; auto kClearKeyUUID = toAidlUuid({0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E}); static const std::string kMimeType = "video/mp4"; static constexpr ::aidl::android::hardware::drm::SecurityLevel kSecurityLevel = ::aidl::android::hardware::drm::SecurityLevel::SW_SECURE_CRYPTO; bool drmClearkey = false; auto ret = drmFactory->isCryptoSchemeSupported(toAidlUuid(kClearKeyUUID), kMimeType, kSecurityLevel, &drmClearkey); if (!drmClearkey) { if (!isCryptoSchemeSupported(kClearKeyUUID, kSecurityLevel, kMimeType)) { GTEST_SKIP() << "ClearKey not supported by " << GetParamService(); } } Loading Loading
drm/aidl/vts/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ cc_test { "android.hardware.drm@1.0-helper", "android.hardware.drm-V1-ndk", "android.hardware.common-V2-ndk", "libaidlcommonsupport", "libgmock_ndk", "libdrmvtshelper", "libvtsclearkey", ], Loading
drm/aidl/vts/drm_hal_common.cpp +75 −50 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ #include <sys/mman.h> #include <random> #include <aidlcommonsupport/NativeHandle.h> #include <android/binder_manager.h> #include <android/binder_process.h> #include <android/sharedmem.h> #include <cutils/native_handle.h> #include "drm_hal_clearkey_module.h" #include "drm_hal_common.h" Loading @@ -39,8 +41,7 @@ namespace clearkeydrm = ::android::hardware::drm::V1_2::vts; using std::vector; using ::aidl::android::hardware::common::Ashmem; using ::aidl::android::hardware::drm::BufferType; using ::aidl::android::hardware::drm::DecryptResult; using ::aidl::android::hardware::drm::DecryptArgs; using ::aidl::android::hardware::drm::DestinationBuffer; using ::aidl::android::hardware::drm::EventType; using ::aidl::android::hardware::drm::ICryptoPlugin; Loading Loading @@ -72,7 +73,6 @@ std::string HalBaseName(const std::string& fullname) { } const char* kDrmIface = "android.hardware.drm.IDrmFactory"; const char* kCryptoIface = "android.hardware.drm.ICryptoFactory"; std::string HalFullName(const std::string& iface, const std::string& basename) { return iface + '/' + basename; Loading Loading @@ -184,7 +184,6 @@ void DrmHalTest::SetUp() { test_info->name(), GetParamService().c_str()); auto svc = GetParamService(); const string cryptoInstance = HalFullName(kCryptoIface, svc); const string drmInstance = HalFullName(kDrmIface, svc); if (drmInstance.find("IDrmFactory") != std::string::npos) { Loading @@ -192,12 +191,6 @@ void DrmHalTest::SetUp() { ::ndk::SpAIBinder(AServiceManager_waitForService(drmInstance.c_str()))); ASSERT_NE(drmFactory, nullptr); drmPlugin = createDrmPlugin(); } if (cryptoInstance.find("ICryptoFactory") != std::string::npos) { cryptoFactory = ICryptoFactory::fromBinder( ::ndk::SpAIBinder(AServiceManager_waitForService(cryptoInstance.c_str()))); ASSERT_NE(cryptoFactory, nullptr); cryptoPlugin = createCryptoPlugin(); } Loading @@ -211,14 +204,12 @@ void DrmHalTest::SetUp() { contentConfigurations = vendorModule->getContentConfigurations(); // If drm scheme not installed skip subsequent tests bool result = false; drmFactory->isCryptoSchemeSupported({getUUID()}, "cenc", SecurityLevel::SW_SECURE_CRYPTO, &result); bool result = isCryptoSchemeSupported(getAidlUUID(), SecurityLevel::SW_SECURE_CRYPTO, "cenc"); if (!result) { if (GetParamUUID() == std::array<uint8_t, 16>()) { GTEST_SKIP() << "vendor module drm scheme not supported"; } else { FAIL() << "param scheme must not supported"; FAIL() << "param scheme must be supported"; } } Loading @@ -234,18 +225,18 @@ std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin> DrmHalTest::createDr } std::string packageName("aidl.android.hardware.drm.test"); std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin> result; auto ret = drmFactory->createPlugin({getUUID()}, packageName, &result); auto ret = drmFactory->createDrmPlugin(getAidlUUID(), packageName, &result); EXPECT_OK(ret) << "createDrmPlugin remote call failed"; return result; } std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin> DrmHalTest::createCryptoPlugin() { if (cryptoFactory == nullptr) { if (drmFactory == nullptr) { return nullptr; } vector<uint8_t> initVec; std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin> result; auto ret = cryptoFactory->createPlugin({getUUID()}, initVec, &result); auto ret = drmFactory->createCryptoPlugin(getAidlUUID(), initVec, &result); EXPECT_OK(ret) << "createCryptoPlugin remote call failed"; return result; } Loading @@ -270,6 +261,26 @@ std::vector<uint8_t> DrmHalTest::getVendorUUID() { return vendorModule->getUUID(); } bool DrmHalTest::isCryptoSchemeSupported(Uuid uuid, SecurityLevel level, std::string mime) { CryptoSchemes schemes{}; auto ret = drmFactory->getSupportedCryptoSchemes(&schemes); EXPECT_OK(ret); if (!ret.isOk() || !std::count(schemes.uuids.begin(), schemes.uuids.end(), uuid)) { return false; } if (level > schemes.maxLevel || level < schemes.minLevel) { if (level != SecurityLevel::DEFAULT && level != SecurityLevel::UNKNOWN) { return false; } } if (!mime.empty()) { if (!std::count(schemes.mimeTypes.begin(), schemes.mimeTypes.end(), mime)) { return false; } } return true; } void DrmHalTest::provision() { std::string certificateType; std::string certificateAuthority; Loading Loading @@ -410,38 +421,43 @@ KeyedVector DrmHalTest::toAidlKeyedVector(const map<string, string>& params) { /** * getDecryptMemory allocates memory for decryption, then sets it * as a shared buffer base in the crypto hal. A parcelable Ashmem * is returned. * as a shared buffer base in the crypto hal. An output SharedBuffer * is updated via reference. * * @param size the size of the memory segment to allocate * @param the index of the memory segment which will be used * to refer to it for decryption. */ Ashmem DrmHalTest::getDecryptMemory(size_t size, size_t index) { void DrmHalTest::getDecryptMemory(size_t size, size_t index, SharedBuffer& out) { out.bufferId = static_cast<int32_t>(index); out.offset = 0; out.size = static_cast<int64_t>(size); int fd = ASharedMemory_create("drmVtsSharedMemory", size); EXPECT_GE(fd, 0); EXPECT_EQ(size, ASharedMemory_getSize(fd)); auto handle = native_handle_create(1, 0); handle->data[0] = fd; out.handle = ::android::makeToAidl(handle); Ashmem ashmem; ashmem.fd = ::ndk::ScopedFileDescriptor(fd); ashmem.size = size; EXPECT_OK(cryptoPlugin->setSharedBufferBase(ashmem, index)); return ashmem; EXPECT_OK(cryptoPlugin->setSharedBufferBase(out)); native_handle_delete(handle); } void DrmHalTest::fillRandom(const Ashmem& ashmem) { uint8_t* DrmHalTest::fillRandom(const ::aidl::android::hardware::drm::SharedBuffer& buf) { std::random_device rd; std::mt19937 rand(rd()); ::ndk::ScopedFileDescriptor fd = ashmem.fd.dup(); size_t size = ashmem.size; auto fd = buf.handle.fds[0].get(); size_t size = buf.size; uint8_t* base = static_cast<uint8_t*>( mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)); mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); EXPECT_NE(MAP_FAILED, base); for (size_t i = 0; i < size / sizeof(uint32_t); i++) { auto p = static_cast<uint32_t*>(static_cast<void*>(base)); p[i] = rand(); } return base; } uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, 16>& keyId, Loading @@ -453,6 +469,7 @@ uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, uint8_t localIv[AES_BLOCK_SIZE]; memcpy(localIv, iv, AES_BLOCK_SIZE); vector<uint8_t> ivVec(localIv, localIv + AES_BLOCK_SIZE); vector<uint8_t> keyIdVec(keyId.begin(), keyId.end()); int64_t totalSize = 0; for (size_t i = 0; i < subSamples.size(); i++) { Loading @@ -463,32 +480,39 @@ uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, // The first totalSize bytes of shared memory is the encrypted // input, the second totalSize bytes (if exists) is the decrypted output. size_t factor = expectedStatus == Status::ERROR_DRM_FRAME_TOO_LARGE ? 1 : 2; Ashmem sharedMemory = getDecryptMemory(totalSize * factor, kSegmentIndex); const SharedBuffer sourceBuffer = {.bufferId = kSegmentIndex, .offset = 0, .size = totalSize}; fillRandom(sharedMemory); const DestinationBuffer destBuffer = { .type = BufferType::SHARED_MEMORY, .nonsecureMemory = {.bufferId = kSegmentIndex, .offset = totalSize, .size = totalSize}, .secureMemory = {.fds = {}, .ints = {}}}; const uint64_t offset = 0; uint32_t bytesWritten = 0; vector<uint8_t> keyIdVec(keyId.begin(), keyId.end()); DecryptResult result; auto ret = cryptoPlugin->decrypt(isSecure, keyIdVec, ivVec, mode, pattern, subSamples, sourceBuffer, offset, destBuffer, &result); SharedBuffer sourceBuffer; getDecryptMemory(totalSize * factor, kSegmentIndex, sourceBuffer); auto base = fillRandom(sourceBuffer); SharedBuffer sourceRange; sourceRange.bufferId = kSegmentIndex; sourceRange.offset = 0; sourceRange.size = totalSize; SharedBuffer destRange; destRange.bufferId = kSegmentIndex; destRange.offset = totalSize; destRange.size = totalSize; DecryptArgs args; args.secure = isSecure; args.keyId = keyIdVec; args.iv = ivVec; args.mode = mode; args.pattern = pattern; args.subSamples = subSamples; args.source = std::move(sourceRange); args.offset = 0; args.destination = std::move(destRange); int32_t bytesWritten = 0; auto ret = cryptoPlugin->decrypt(args, &bytesWritten); EXPECT_TXN(ret); EXPECT_EQ(expectedStatus, DrmErr(ret)) << "Unexpected decrypt status " << result.detailedError; bytesWritten = result.bytesWritten; EXPECT_EQ(expectedStatus, DrmErr(ret)) << "Unexpected decrypt status " << ret.getMessage(); if (bytesWritten != totalSize) { return bytesWritten; } ::ndk::ScopedFileDescriptor fd = sharedMemory.fd.dup(); uint8_t* base = static_cast<uint8_t*>( mmap(nullptr, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0)); EXPECT_NE(MAP_FAILED, base); // generate reference vector vector<uint8_t> reference(totalSize); Loading @@ -513,6 +537,7 @@ uint32_t DrmHalTest::decrypt(Mode mode, bool isSecure, const std::array<uint8_t, EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]), static_cast<void*>(base + totalSize), totalSize)) << "decrypt data mismatch"; munmap(base, totalSize * factor); return totalSize; } Loading
drm/aidl/vts/drm_hal_test.cpp +7 −21 Original line number Diff line number Diff line Loading @@ -66,11 +66,8 @@ static constexpr SecurityLevel kHwSecureAll = SecurityLevel::HW_SECURE_ALL; * Ensure drm factory supports module UUID Scheme */ TEST_P(DrmHalTest, VendorUuidSupported) { bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(getAidlUUID(), kVideoMp4, kSwSecureCrypto, &result); ALOGI("kVideoMp4 = %s res %d", kVideoMp4, static_cast<bool>(result)); EXPECT_OK(ret); bool result = isCryptoSchemeSupported(getAidlUUID(), kSwSecureCrypto, kVideoMp4); ALOGI("kVideoMp4 = %s res %d", kVideoMp4, result); EXPECT_TRUE(result); } Loading @@ -80,10 +77,7 @@ TEST_P(DrmHalTest, VendorUuidSupported) { TEST_P(DrmHalTest, InvalidPluginNotSupported) { const vector<uint8_t> kInvalidUUID = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80}; bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(toAidlUuid(kInvalidUUID), kVideoMp4, kSwSecureCrypto, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(toAidlUuid(kInvalidUUID), kSwSecureCrypto, kVideoMp4); EXPECT_FALSE(result); } Loading @@ -93,10 +87,7 @@ TEST_P(DrmHalTest, InvalidPluginNotSupported) { TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) { vector<uint8_t> emptyUUID(16); memset(emptyUUID.data(), 0, 16); bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(toAidlUuid(emptyUUID), kVideoMp4, kSwSecureCrypto, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(toAidlUuid(emptyUUID), kSwSecureCrypto, kVideoMp4); EXPECT_FALSE(result); } Loading @@ -104,10 +95,7 @@ TEST_P(DrmHalTest, EmptyPluginUUIDNotSupported) { * Ensure drm factory doesn't support an invalid mime type */ TEST_P(DrmHalTest, BadMimeNotSupported) { bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(getAidlUUID(), kBadMime, kSwSecureCrypto, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(getAidlUUID(), kSwSecureCrypto, kBadMime); EXPECT_FALSE(result); } Loading Loading @@ -380,9 +368,7 @@ TEST_P(DrmHalTest, EncryptedAesCtrSegmentTestNoKeys) { * Ensure clearkey drm factory doesn't support security level higher than supported */ TEST_P(DrmHalClearkeyTest, BadLevelNotSupported) { bool result = false; auto ret = drmFactory->isCryptoSchemeSupported(getAidlUUID(), kVideoMp4, kHwSecureAll, &result); EXPECT_OK(ret); auto result = isCryptoSchemeSupported(getAidlUUID(), kHwSecureAll, kVideoMp4); EXPECT_FALSE(result); } Loading Loading @@ -461,7 +447,7 @@ TEST_P(DrmHalClearkeyTest, ListenerCallbacks) { const vector<KeyStatus> keyStatusList = { {{0xa, 0xb, 0xc}, KeyStatusType::USABLE}, {{0xd, 0xe, 0xf}, KeyStatusType::EXPIRED}, {{0x0, 0x1, 0x2}, KeyStatusType::USABLEINFUTURE}, {{0x0, 0x1, 0x2}, KeyStatusType::USABLE_IN_FUTURE}, }; EXPECT_EQ(sessionId, args.sessionId); EXPECT_EQ(keyStatusList, args.keyStatusList); Loading
drm/aidl/vts/drm_hal_test_main.cpp +0 −6 Original line number Diff line number Diff line Loading @@ -42,21 +42,15 @@ using drm_vts::DrmHalTestParam; using drm_vts::PrintParamInstanceToString; static const std::vector<DrmHalTestParam> getAllInstances() { using ::aidl::android::hardware::drm::ICryptoFactory; using ::aidl::android::hardware::drm::IDrmFactory; std::vector<std::string> drmInstances = android::getAidlHalInstanceNames(IDrmFactory::descriptor); std::vector<std::string> cryptoInstances = android::getAidlHalInstanceNames(ICryptoFactory::descriptor); std::set<std::string> allInstances; for (auto svc : drmInstances) { allInstances.insert(HalBaseName(svc)); } for (auto svc : cryptoInstances) { allInstances.insert(HalBaseName(svc)); } std::vector<DrmHalTestParam> allInstanceUuidCombos; auto noUUID = [](std::string s) { return DrmHalTestParam(s); }; Loading
drm/aidl/vts/include/drm_hal_common.h +15 −15 Original line number Diff line number Diff line Loading @@ -18,14 +18,17 @@ #include <aidl/android/hardware/common/Ashmem.h> #include <aidl/android/hardware/drm/BnDrmPluginListener.h> #include <aidl/android/hardware/drm/ICryptoFactory.h> #include <aidl/android/hardware/drm/ICryptoPlugin.h> #include <aidl/android/hardware/drm/IDrmFactory.h> #include <aidl/android/hardware/drm/IDrmPlugin.h> #include <aidl/android/hardware/drm/IDrmPluginListener.h> #include <aidl/android/hardware/drm/Status.h> #include <android/binder_auto_utils.h> #include <gmock/gmock.h> #include <array> #include <algorithm> #include <chrono> #include <future> #include <iostream> Loading @@ -35,8 +38,6 @@ #include <utility> #include <vector> #include <android/binder_auto_utils.h> #include "VtsHalHidlTargetCallbackBase.h" #include "drm_hal_vendor_module_api.h" #include "drm_vts_helper.h" Loading Loading @@ -80,11 +81,14 @@ class DrmHalTest : public ::testing::TestWithParam<DrmHalTestParam> { std::array<uint8_t, 16> GetParamUUID() { return GetParam().scheme_; } std::string GetParamService() { return GetParam().instance_; } ::aidl::android::hardware::drm::Uuid toAidlUuid(const std::vector<uint8_t>& in_uuid) { ::aidl::android::hardware::drm::Uuid uuid; uuid.uuid = in_uuid; return uuid; std::array<uint8_t, 16> a; std::copy_n(in_uuid.begin(), a.size(), a.begin()); return {a}; } bool isCryptoSchemeSupported(::aidl::android::hardware::drm::Uuid uuid, ::aidl::android::hardware::drm::SecurityLevel level, std::string mime); void provision(); SessionId openSession(::aidl::android::hardware::drm::SecurityLevel level, ::aidl::android::hardware::drm::Status* err); Loading @@ -106,8 +110,8 @@ class DrmHalTest : public ::testing::TestWithParam<DrmHalTestParam> { KeyedVector toAidlKeyedVector(const std::map<std::string, std::string>& params); std::array<uint8_t, 16> toStdArray(const std::vector<uint8_t>& vec); void fillRandom(const ::aidl::android::hardware::common::Ashmem& ashmem); ::aidl::android::hardware::common::Ashmem getDecryptMemory(size_t size, size_t index); uint8_t* fillRandom(const ::aidl::android::hardware::drm::SharedBuffer& buf); void getDecryptMemory(size_t size, size_t index, SharedBuffer& buf); uint32_t decrypt(::aidl::android::hardware::drm::Mode mode, bool isSecure, const std::array<uint8_t, 16>& keyId, uint8_t* iv, Loading @@ -123,7 +127,6 @@ class DrmHalTest : public ::testing::TestWithParam<DrmHalTestParam> { const std::vector<uint8_t>& key); std::shared_ptr<::aidl::android::hardware::drm::IDrmFactory> drmFactory; std::shared_ptr<::aidl::android::hardware::drm::ICryptoFactory> cryptoFactory; std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin> drmPlugin; std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin> cryptoPlugin; Loading @@ -139,16 +142,13 @@ class DrmHalClearkeyTest : public DrmHalTest { public: virtual void SetUp() override { DrmHalTest::SetUp(); const std::vector<uint8_t> kClearKeyUUID = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E}; auto kClearKeyUUID = toAidlUuid({0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E}); static const std::string kMimeType = "video/mp4"; static constexpr ::aidl::android::hardware::drm::SecurityLevel kSecurityLevel = ::aidl::android::hardware::drm::SecurityLevel::SW_SECURE_CRYPTO; bool drmClearkey = false; auto ret = drmFactory->isCryptoSchemeSupported(toAidlUuid(kClearKeyUUID), kMimeType, kSecurityLevel, &drmClearkey); if (!drmClearkey) { if (!isCryptoSchemeSupported(kClearKeyUUID, kSecurityLevel, kMimeType)) { GTEST_SKIP() << "ClearKey not supported by " << GetParamService(); } } Loading