Loading drm/libmediadrm/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -28,7 +28,11 @@ cc_library { "DrmSessionManager.cpp", "SharedLibrary.cpp", "DrmHal.cpp", "DrmHalHidl.cpp", "DrmHalAidl.cpp", "CryptoHal.cpp", "CryptoHalHidl.cpp", "CryptoHalAidl.cpp", "DrmUtils.cpp", ], Loading Loading @@ -63,10 +67,12 @@ cc_library { "android.hardware.drm@1.4", "libhidlallocatorutils", "libhidlbase", "android.hardware.drm-V1-ndk", ], static_libs: [ "resourcemanager_aidl_interface-ndk", "libaidlcommonsupport", ], export_shared_lib_headers: [ Loading drm/libmediadrm/CryptoHal.cpp +59 −348 Original line number Diff line number Diff line Loading @@ -16,389 +16,100 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "CryptoHal" #include <utils/Log.h> #include <android/hardware/drm/1.0/types.h> #include <android/hidl/manager/1.2/IServiceManager.h> #include <hidl/ServiceManagement.h> #include <hidlmemory/FrameworkUtils.h> #include <media/hardware/CryptoAPI.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AString.h> #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/MediaErrors.h> #include <mediadrm/CryptoHal.h> #include <mediadrm/CryptoHalHidl.h> #include <mediadrm/CryptoHalAidl.h> #include <mediadrm/DrmUtils.h> using drm::V1_0::BufferType; using drm::V1_0::DestinationBuffer; using drm::V1_0::ICryptoFactory; using drm::V1_0::ICryptoPlugin; using drm::V1_0::Mode; using drm::V1_0::Pattern; using drm::V1_0::SharedBuffer; using drm::V1_0::Status; using drm::V1_0::SubSample; using ::android::DrmUtils::toStatusT; using ::android::hardware::hidl_array; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::HidlMemory; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; typedef drm::V1_2::Status Status_V1_2; namespace android { static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) { hidl_vec<uint8_t> vec; vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size()); return vec; } static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) { hidl_vec<uint8_t> vec; vec.resize(size); memcpy(vec.data(), ptr, size); return vec; } static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) { if (!ptr) { return hidl_array<uint8_t, 16>(); } return hidl_array<uint8_t, 16>(ptr); } static String8 toString8(hidl_string hString) { return String8(hString.c_str()); } CryptoHal::CryptoHal() : mFactories(makeCryptoFactories()), mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT), mHeapSeqNum(0) { } CryptoHal::~CryptoHal() { } Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() { Vector<sp<ICryptoFactory>> factories; auto manager = hardware::defaultServiceManager1_2(); if (manager != NULL) { manager->listManifestByInterface(drm::V1_0::ICryptoFactory::descriptor, [&factories](const hidl_vec<hidl_string> ®istered) { for (const auto &instance : registered) { auto factory = drm::V1_0::ICryptoFactory::getService(instance); if (factory != NULL) { ALOGD("found drm@1.0 ICryptoFactory %s", instance.c_str()); factories.push_back(factory); } } } ); manager->listManifestByInterface(drm::V1_1::ICryptoFactory::descriptor, [&factories](const hidl_vec<hidl_string> ®istered) { for (const auto &instance : registered) { auto factory = drm::V1_1::ICryptoFactory::getService(instance); if (factory != NULL) { ALOGD("found drm@1.1 ICryptoFactory %s", instance.c_str()); factories.push_back(factory); } } } ); } if (factories.size() == 0) { // must be in passthrough mode, load the default passthrough service auto passthrough = ICryptoFactory::getService(); if (passthrough != NULL) { ALOGI("makeCryptoFactories: using default passthrough crypto instance"); factories.push_back(passthrough); } else { ALOGE("Failed to find any crypto factories"); } } return factories; } sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory, const uint8_t uuid[16], const void *initData, size_t initDataSize) { sp<ICryptoPlugin> plugin; Return<void> hResult = factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize), [&](Status status, const sp<ICryptoPlugin>& hPlugin) { if (status != Status::OK) { ALOGE("Failed to make crypto plugin"); return; } plugin = hPlugin; } ); if (!hResult.isOk()) { mInitCheck = DEAD_OBJECT; } return plugin; CryptoHal::CryptoHal() { mCryptoHalAidl = sp<CryptoHalAidl>::make(); mCryptoHalHidl = sp<CryptoHalHidl>::make(); } CryptoHal::~CryptoHal() {} status_t CryptoHal::initCheck() const { return mInitCheck; if (mCryptoHalAidl->initCheck() == OK || mCryptoHalHidl->initCheck() == OK) return OK; if (mCryptoHalAidl->initCheck() == NO_INIT || mCryptoHalHidl->initCheck() == NO_INIT) return NO_INIT; return mCryptoHalHidl->initCheck(); } bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) { Mutex::Autolock autoLock(mLock); for (size_t i = 0; i < mFactories.size(); i++) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { return true; } } return false; return mCryptoHalAidl->isCryptoSchemeSupported(uuid) || mCryptoHalHidl->isCryptoSchemeSupported(uuid); } status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data, size_t size) { Mutex::Autolock autoLock(mLock); for (size_t i = 0; i < mFactories.size(); i++) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size); if (mPlugin != NULL) { mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin); } } } if (mInitCheck == NO_INIT) { mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK; } return mInitCheck; status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void* data, size_t size) { if (mCryptoHalAidl->createPlugin(uuid, data, size) != OK) return mCryptoHalHidl->createPlugin(uuid, data, size); return OK; } status_t CryptoHal::destroyPlugin() { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return mInitCheck; } mPlugin.clear(); mPluginV1_2.clear(); return OK; // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->destroyPlugin(); return mCryptoHalHidl->destroyPlugin(); } bool CryptoHal::requiresSecureDecoderComponent(const char* mime) const { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return false; } Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime)); if (!hResult.isOk()) { return false; } return hResult; } /** * If the heap base isn't set, get the heap base from the HidlMemory * and send it to the HAL so it can map a remote heap of the same * size. Once the heap base is established, shared memory buffers * are sent by providing an offset into the heap and a buffer size. */ int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) { if (heap == NULL || mHeapSeqNum < 0) { ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum); return -1; } Mutex::Autolock autoLock(mLock); int32_t seqNum = mHeapSeqNum++; uint32_t bufferId = static_cast<uint32_t>(seqNum); mHeapSizes.add(seqNum, heap->size()); Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId); ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); return seqNum; } void CryptoHal::clearHeapBase(int32_t seqNum) { Mutex::Autolock autoLock(mLock); /* * Clear the remote shared memory mapping by setting the shared * buffer base to a null hidl_memory. * * TODO: Add a releaseSharedBuffer method in a future DRM HAL * API version to make this explicit. */ ssize_t index = mHeapSizes.indexOfKey(seqNum); if (index >= 0) { if (mPlugin != NULL) { uint32_t bufferId = static_cast<uint32_t>(seqNum); Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId); ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); } mHeapSizes.removeItem(seqNum); } } status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) { int32_t seqNum = static_cast<int32_t>(buffer.bufferId); // memory must be in one of the heaps that have been set if (mHeapSizes.indexOfKey(seqNum) < 0) { return UNKNOWN_ERROR; } // memory must be within the address space of the heap size_t heapSize = mHeapSizes.valueFor(seqNum); if (heapSize < buffer.offset + buffer.size || SIZE_MAX - buffer.offset < buffer.size) { android_errorWriteLog(0x534e4554, "76221123"); return UNKNOWN_ERROR; } return OK; } ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern, const ::SharedBuffer &hSource, size_t offset, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, const ::DestinationBuffer &hDestination, AString *errorDetailMsg) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return mInitCheck; } Mode hMode; switch(mode) { case CryptoPlugin::kMode_Unencrypted: hMode = Mode::UNENCRYPTED ; break; case CryptoPlugin::kMode_AES_CTR: hMode = Mode::AES_CTR; break; case CryptoPlugin::kMode_AES_WV: hMode = Mode::AES_CBC_CTS; break; case CryptoPlugin::kMode_AES_CBC: hMode = Mode::AES_CBC; break; default: return UNKNOWN_ERROR; } Pattern hPattern; hPattern.encryptBlocks = pattern.mEncryptBlocks; hPattern.skipBlocks = pattern.mSkipBlocks; std::vector<SubSample> stdSubSamples; for (size_t i = 0; i < numSubSamples; i++) { SubSample subSample; subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData; subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData; stdSubSamples.push_back(subSample); } auto hSubSamples = hidl_vec<SubSample>(stdSubSamples); bool secure; if (hDestination.type == BufferType::SHARED_MEMORY) { status_t status = checkSharedBuffer(hDestination.nonsecureMemory); if (status != OK) { return status; } secure = false; } else if (hDestination.type == BufferType::NATIVE_HANDLE) { secure = true; } else { android_errorWriteLog(0x534e4554, "70526702"); return UNKNOWN_ERROR; } status_t status = checkSharedBuffer(hSource); if (status != OK) { return status; } status_t err = UNKNOWN_ERROR; uint32_t bytesWritten = 0; Return<void> hResult; mLock.unlock(); if (mPluginV1_2 != NULL) { hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status_V1_2::OK) { bytesWritten = hBytesWritten; *errorDetailMsg = toString8(hDetailedError); } err = toStatusT(status); } ); } else { hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status::OK) { bytesWritten = hBytesWritten; *errorDetailMsg = toString8(hDetailedError); } err = toStatusT(status); } ); } err = hResult.isOk() ? err : DEAD_OBJECT; if (err == OK) { return bytesWritten; } return err; // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->requiresSecureDecoderComponent(mime); return mCryptoHalHidl->requiresSecureDecoderComponent(mime); } void CryptoHal::notifyResolution(uint32_t width, uint32_t height) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) { mCryptoHalAidl->notifyResolution(width, height); return; } auto hResult = mPlugin->notifyResolution(width, height); ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str()); mCryptoHalHidl->notifyResolution(width, height); } status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return mInitCheck; // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId); return mCryptoHalHidl->setMediaDrmSession(sessionId); } ssize_t CryptoHal::decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source, size_t offset, const CryptoPlugin::SubSample* subSamples, size_t numSubSamples, const ::DestinationBuffer& destination, AString* errorDetailMsg) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->decrypt(key, iv, mode, pattern, source, offset, subSamples, numSubSamples, destination, errorDetailMsg); return mCryptoHalHidl->decrypt(key, iv, mode, pattern, source, offset, subSamples, numSubSamples, destination, errorDetailMsg); } int32_t CryptoHal::setHeap(const sp<HidlMemory>& heap) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setHeap(heap); return mCryptoHalHidl->setHeap(heap); } void CryptoHal::unsetHeap(int32_t seqNum) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) { mCryptoHalAidl->unsetHeap(seqNum); return; } auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId)); return err.isOk() ? toStatusT(err) : DEAD_OBJECT; mCryptoHalHidl->unsetHeap(seqNum); } status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const { Mutex::Autolock autoLock(mLock); return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs); // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->getLogMessages(logs); return mCryptoHalHidl->getLogMessages(logs); } } // namespace android No newline at end of file Loading
drm/libmediadrm/Android.bp +6 −0 Original line number Diff line number Diff line Loading @@ -28,7 +28,11 @@ cc_library { "DrmSessionManager.cpp", "SharedLibrary.cpp", "DrmHal.cpp", "DrmHalHidl.cpp", "DrmHalAidl.cpp", "CryptoHal.cpp", "CryptoHalHidl.cpp", "CryptoHalAidl.cpp", "DrmUtils.cpp", ], Loading Loading @@ -63,10 +67,12 @@ cc_library { "android.hardware.drm@1.4", "libhidlallocatorutils", "libhidlbase", "android.hardware.drm-V1-ndk", ], static_libs: [ "resourcemanager_aidl_interface-ndk", "libaidlcommonsupport", ], export_shared_lib_headers: [ Loading
drm/libmediadrm/CryptoHal.cpp +59 −348 Original line number Diff line number Diff line Loading @@ -16,389 +16,100 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "CryptoHal" #include <utils/Log.h> #include <android/hardware/drm/1.0/types.h> #include <android/hidl/manager/1.2/IServiceManager.h> #include <hidl/ServiceManagement.h> #include <hidlmemory/FrameworkUtils.h> #include <media/hardware/CryptoAPI.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AString.h> #include <media/stagefright/foundation/hexdump.h> #include <media/stagefright/MediaErrors.h> #include <mediadrm/CryptoHal.h> #include <mediadrm/CryptoHalHidl.h> #include <mediadrm/CryptoHalAidl.h> #include <mediadrm/DrmUtils.h> using drm::V1_0::BufferType; using drm::V1_0::DestinationBuffer; using drm::V1_0::ICryptoFactory; using drm::V1_0::ICryptoPlugin; using drm::V1_0::Mode; using drm::V1_0::Pattern; using drm::V1_0::SharedBuffer; using drm::V1_0::Status; using drm::V1_0::SubSample; using ::android::DrmUtils::toStatusT; using ::android::hardware::hidl_array; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::HidlMemory; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; typedef drm::V1_2::Status Status_V1_2; namespace android { static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) { hidl_vec<uint8_t> vec; vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size()); return vec; } static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) { hidl_vec<uint8_t> vec; vec.resize(size); memcpy(vec.data(), ptr, size); return vec; } static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) { if (!ptr) { return hidl_array<uint8_t, 16>(); } return hidl_array<uint8_t, 16>(ptr); } static String8 toString8(hidl_string hString) { return String8(hString.c_str()); } CryptoHal::CryptoHal() : mFactories(makeCryptoFactories()), mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT), mHeapSeqNum(0) { } CryptoHal::~CryptoHal() { } Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() { Vector<sp<ICryptoFactory>> factories; auto manager = hardware::defaultServiceManager1_2(); if (manager != NULL) { manager->listManifestByInterface(drm::V1_0::ICryptoFactory::descriptor, [&factories](const hidl_vec<hidl_string> ®istered) { for (const auto &instance : registered) { auto factory = drm::V1_0::ICryptoFactory::getService(instance); if (factory != NULL) { ALOGD("found drm@1.0 ICryptoFactory %s", instance.c_str()); factories.push_back(factory); } } } ); manager->listManifestByInterface(drm::V1_1::ICryptoFactory::descriptor, [&factories](const hidl_vec<hidl_string> ®istered) { for (const auto &instance : registered) { auto factory = drm::V1_1::ICryptoFactory::getService(instance); if (factory != NULL) { ALOGD("found drm@1.1 ICryptoFactory %s", instance.c_str()); factories.push_back(factory); } } } ); } if (factories.size() == 0) { // must be in passthrough mode, load the default passthrough service auto passthrough = ICryptoFactory::getService(); if (passthrough != NULL) { ALOGI("makeCryptoFactories: using default passthrough crypto instance"); factories.push_back(passthrough); } else { ALOGE("Failed to find any crypto factories"); } } return factories; } sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory, const uint8_t uuid[16], const void *initData, size_t initDataSize) { sp<ICryptoPlugin> plugin; Return<void> hResult = factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize), [&](Status status, const sp<ICryptoPlugin>& hPlugin) { if (status != Status::OK) { ALOGE("Failed to make crypto plugin"); return; } plugin = hPlugin; } ); if (!hResult.isOk()) { mInitCheck = DEAD_OBJECT; } return plugin; CryptoHal::CryptoHal() { mCryptoHalAidl = sp<CryptoHalAidl>::make(); mCryptoHalHidl = sp<CryptoHalHidl>::make(); } CryptoHal::~CryptoHal() {} status_t CryptoHal::initCheck() const { return mInitCheck; if (mCryptoHalAidl->initCheck() == OK || mCryptoHalHidl->initCheck() == OK) return OK; if (mCryptoHalAidl->initCheck() == NO_INIT || mCryptoHalHidl->initCheck() == NO_INIT) return NO_INIT; return mCryptoHalHidl->initCheck(); } bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) { Mutex::Autolock autoLock(mLock); for (size_t i = 0; i < mFactories.size(); i++) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { return true; } } return false; return mCryptoHalAidl->isCryptoSchemeSupported(uuid) || mCryptoHalHidl->isCryptoSchemeSupported(uuid); } status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data, size_t size) { Mutex::Autolock autoLock(mLock); for (size_t i = 0; i < mFactories.size(); i++) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size); if (mPlugin != NULL) { mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin); } } } if (mInitCheck == NO_INIT) { mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK; } return mInitCheck; status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void* data, size_t size) { if (mCryptoHalAidl->createPlugin(uuid, data, size) != OK) return mCryptoHalHidl->createPlugin(uuid, data, size); return OK; } status_t CryptoHal::destroyPlugin() { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return mInitCheck; } mPlugin.clear(); mPluginV1_2.clear(); return OK; // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->destroyPlugin(); return mCryptoHalHidl->destroyPlugin(); } bool CryptoHal::requiresSecureDecoderComponent(const char* mime) const { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return false; } Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime)); if (!hResult.isOk()) { return false; } return hResult; } /** * If the heap base isn't set, get the heap base from the HidlMemory * and send it to the HAL so it can map a remote heap of the same * size. Once the heap base is established, shared memory buffers * are sent by providing an offset into the heap and a buffer size. */ int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) { if (heap == NULL || mHeapSeqNum < 0) { ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum); return -1; } Mutex::Autolock autoLock(mLock); int32_t seqNum = mHeapSeqNum++; uint32_t bufferId = static_cast<uint32_t>(seqNum); mHeapSizes.add(seqNum, heap->size()); Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId); ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); return seqNum; } void CryptoHal::clearHeapBase(int32_t seqNum) { Mutex::Autolock autoLock(mLock); /* * Clear the remote shared memory mapping by setting the shared * buffer base to a null hidl_memory. * * TODO: Add a releaseSharedBuffer method in a future DRM HAL * API version to make this explicit. */ ssize_t index = mHeapSizes.indexOfKey(seqNum); if (index >= 0) { if (mPlugin != NULL) { uint32_t bufferId = static_cast<uint32_t>(seqNum); Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId); ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); } mHeapSizes.removeItem(seqNum); } } status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) { int32_t seqNum = static_cast<int32_t>(buffer.bufferId); // memory must be in one of the heaps that have been set if (mHeapSizes.indexOfKey(seqNum) < 0) { return UNKNOWN_ERROR; } // memory must be within the address space of the heap size_t heapSize = mHeapSizes.valueFor(seqNum); if (heapSize < buffer.offset + buffer.size || SIZE_MAX - buffer.offset < buffer.size) { android_errorWriteLog(0x534e4554, "76221123"); return UNKNOWN_ERROR; } return OK; } ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern, const ::SharedBuffer &hSource, size_t offset, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, const ::DestinationBuffer &hDestination, AString *errorDetailMsg) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return mInitCheck; } Mode hMode; switch(mode) { case CryptoPlugin::kMode_Unencrypted: hMode = Mode::UNENCRYPTED ; break; case CryptoPlugin::kMode_AES_CTR: hMode = Mode::AES_CTR; break; case CryptoPlugin::kMode_AES_WV: hMode = Mode::AES_CBC_CTS; break; case CryptoPlugin::kMode_AES_CBC: hMode = Mode::AES_CBC; break; default: return UNKNOWN_ERROR; } Pattern hPattern; hPattern.encryptBlocks = pattern.mEncryptBlocks; hPattern.skipBlocks = pattern.mSkipBlocks; std::vector<SubSample> stdSubSamples; for (size_t i = 0; i < numSubSamples; i++) { SubSample subSample; subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData; subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData; stdSubSamples.push_back(subSample); } auto hSubSamples = hidl_vec<SubSample>(stdSubSamples); bool secure; if (hDestination.type == BufferType::SHARED_MEMORY) { status_t status = checkSharedBuffer(hDestination.nonsecureMemory); if (status != OK) { return status; } secure = false; } else if (hDestination.type == BufferType::NATIVE_HANDLE) { secure = true; } else { android_errorWriteLog(0x534e4554, "70526702"); return UNKNOWN_ERROR; } status_t status = checkSharedBuffer(hSource); if (status != OK) { return status; } status_t err = UNKNOWN_ERROR; uint32_t bytesWritten = 0; Return<void> hResult; mLock.unlock(); if (mPluginV1_2 != NULL) { hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status_V1_2::OK) { bytesWritten = hBytesWritten; *errorDetailMsg = toString8(hDetailedError); } err = toStatusT(status); } ); } else { hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, hPattern, hSubSamples, hSource, offset, hDestination, [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) { if (status == Status::OK) { bytesWritten = hBytesWritten; *errorDetailMsg = toString8(hDetailedError); } err = toStatusT(status); } ); } err = hResult.isOk() ? err : DEAD_OBJECT; if (err == OK) { return bytesWritten; } return err; // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->requiresSecureDecoderComponent(mime); return mCryptoHalHidl->requiresSecureDecoderComponent(mime); } void CryptoHal::notifyResolution(uint32_t width, uint32_t height) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) { mCryptoHalAidl->notifyResolution(width, height); return; } auto hResult = mPlugin->notifyResolution(width, height); ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str()); mCryptoHalHidl->notifyResolution(width, height); } status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) { Mutex::Autolock autoLock(mLock); if (mInitCheck != OK) { return mInitCheck; // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId); return mCryptoHalHidl->setMediaDrmSession(sessionId); } ssize_t CryptoHal::decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source, size_t offset, const CryptoPlugin::SubSample* subSamples, size_t numSubSamples, const ::DestinationBuffer& destination, AString* errorDetailMsg) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->decrypt(key, iv, mode, pattern, source, offset, subSamples, numSubSamples, destination, errorDetailMsg); return mCryptoHalHidl->decrypt(key, iv, mode, pattern, source, offset, subSamples, numSubSamples, destination, errorDetailMsg); } int32_t CryptoHal::setHeap(const sp<HidlMemory>& heap) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setHeap(heap); return mCryptoHalHidl->setHeap(heap); } void CryptoHal::unsetHeap(int32_t seqNum) { // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) { mCryptoHalAidl->unsetHeap(seqNum); return; } auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId)); return err.isOk() ? toStatusT(err) : DEAD_OBJECT; mCryptoHalHidl->unsetHeap(seqNum); } status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const { Mutex::Autolock autoLock(mLock); return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs); // This requires plugin to be created. if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->getLogMessages(logs); return mCryptoHalHidl->getLogMessages(logs); } } // namespace android No newline at end of file