Add aidl interface support for Drm Framework
This change intends to make DrmHal/CryptoHal layer support aidl
interface implemented plugins.
Test: CtsMediaDrmTestCases, GtsMediaTestCases
Bug: 200055138
Bug: 170964303
Change-Id: I7056adf184acf1463cb4fc85e1c95ac88c2097f6
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 71df58c..6e1e10b 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -28,7 +28,11 @@
"DrmSessionManager.cpp",
"SharedLibrary.cpp",
"DrmHal.cpp",
+ "DrmHalHidl.cpp",
+ "DrmHalAidl.cpp",
"CryptoHal.cpp",
+ "CryptoHalHidl.cpp",
+ "CryptoHalAidl.cpp",
"DrmUtils.cpp",
],
@@ -63,10 +67,12 @@
"android.hardware.drm@1.4",
"libhidlallocatorutils",
"libhidlbase",
+ "android.hardware.drm-V1-ndk",
],
static_libs: [
"resourcemanager_aidl_interface-ndk",
+ "libaidlcommonsupport",
],
export_shared_lib_headers: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index e0db1c4..f95d527 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -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;
+CryptoHal::CryptoHal() {
+ mCryptoHalAidl = sp<CryptoHalAidl>::make();
+ mCryptoHalHidl = sp<CryptoHalHidl>::make();
}
-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() {}
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;
+bool CryptoHal::requiresSecureDecoderComponent(const char* mime) const {
+ // 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);
+status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
+ return mCryptoHalHidl->setMediaDrmSession(sessionId);
+}
- if (mInitCheck != OK) {
- return mInitCheck;
+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);
+status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ // This requires plugin to be created.
+ if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->getLogMessages(logs);
+ return mCryptoHalHidl->getLogMessages(logs);
}
-} // namespace android
+
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
new file mode 100644
index 0000000..a688728
--- /dev/null
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CryptoHalAidl"
+
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/CryptoHalAidl.h>
+#include <mediadrm/DrmUtils.h>
+
+using ::aidl::android::hardware::drm::BufferType;
+using ::aidl::android::hardware::drm::DecryptResult;
+using DestinationBufferAidl = ::aidl::android::hardware::drm::DestinationBuffer;
+using ::aidl::android::hardware::drm::Mode;
+using ::aidl::android::hardware::drm::Pattern;
+using SharedBufferAidl = ::aidl::android::hardware::drm::SharedBuffer;
+using ::aidl::android::hardware::drm::Status;
+using ::aidl::android::hardware::drm::SubSample;
+using ::aidl::android::hardware::drm::Uuid;
+
+using ::aidl::android::hardware::common::Ashmem;
+
+using ::android::sp;
+using ::android::DrmUtils::toStatusTAidl;
+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 ::aidl::android::hardware::drm::Uuid;
+// -------Hidl interface related-----------------
+// TODO: replace before removing hidl interface
+
+using BufferTypeHidl = ::android::hardware::drm::V1_0::BufferType;
+using SharedBufferHidl = ::android::hardware::drm::V1_0::SharedBuffer;
+using DestinationBufferHidl = ::android::hardware::drm::V1_0::DestinationBuffer;
+
+// -------Hidl interface related end-------------
+
+namespace android {
+
+static Uuid toAidlUuid(const uint8_t* uuid) {
+ Uuid uuidAidl;
+ uuidAidl.uuid = std::vector<uint8_t>(uuid, uuid + 16);
+ return uuidAidl;
+}
+
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t>& vector) {
+ auto v = reinterpret_cast<const Byte*>(vector.array());
+ std::vector<Byte> vec(v, v + vector.size());
+ return vec;
+}
+
+// -------Hidl interface related-----------------
+// TODO: replace before removing hidl interface
+status_t CryptoHalAidl::checkSharedBuffer(const SharedBufferHidl& 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;
+}
+
+static SharedBufferAidl hidlSharedBufferToAidlSharedBuffer(const SharedBufferHidl& buffer) {
+ SharedBufferAidl aidlsb;
+ aidlsb.bufferId = buffer.bufferId;
+ aidlsb.offset = buffer.offset;
+ aidlsb.size = buffer.size;
+ return aidlsb;
+}
+
+static DestinationBufferAidl hidlDestinationBufferToAidlDestinationBuffer(
+ const DestinationBufferHidl& buffer) {
+ DestinationBufferAidl aidldb;
+ // skip negative convert check as count of enum elements are 2
+ aidldb.type = static_cast<BufferType>((int32_t)buffer.type);
+ aidldb.nonsecureMemory = hidlSharedBufferToAidlSharedBuffer(buffer.nonsecureMemory);
+ aidldb.secureMemory = ::android::makeToAidl(buffer.secureMemory.getNativeHandle());
+ return aidldb;
+}
+
+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 const Vector<uint8_t> toVector(const std::vector<uint8_t>& vec) {
+ Vector<uint8_t> vector;
+ vector.appendArray(vec.data(), vec.size());
+ return *const_cast<const Vector<uint8_t>*>(&vector);
+}
+
+static String8 toString8(const std::string& string) {
+ return String8(string.c_str());
+}
+
+// -------Hidl interface related end--------------
+
+CryptoHalAidl::CryptoHalAidl()
+ : mFactories(makeCryptoFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
+ mHeapSeqNum(0) {}
+
+CryptoHalAidl::~CryptoHalAidl() {}
+
+std::vector<std::shared_ptr<ICryptoFactoryAidl>> CryptoHalAidl::makeCryptoFactories() {
+ std::vector<std::shared_ptr<ICryptoFactoryAidl>> factories;
+ AServiceManager_forEachDeclaredInstance(
+ ICryptoFactoryAidl::descriptor, static_cast<void*>(&factories),
+ [](const char* instance, void* context) {
+ auto fullName = std::string(ICryptoFactoryAidl::descriptor) + "/" + std::string(instance);
+ auto factory = ICryptoFactoryAidl::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_getService(fullName.c_str())));
+ if (factory == nullptr) {
+ ALOGE("not found ICryptoFactoryAidl. Instance name:[%s]", fullName.c_str());
+ return;
+ }
+
+ ALOGI("found ICryptoFactoryAidl. Instance name:[%s]", fullName.c_str());
+ static_cast<std::vector<std::shared_ptr<ICryptoFactoryAidl>>*>(context)
+ ->emplace_back(factory);
+ });
+
+ return factories;
+}
+
+status_t CryptoHalAidl::initCheck() const {
+ return mInitCheck;
+}
+
+bool CryptoHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+
+ bool isSupported = false;
+ Uuid uuidAidl = toAidlUuid(uuid);
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuidAidl, &isSupported).isOk()) {
+ if (isSupported) break;
+ }
+ }
+ return isSupported;
+}
+
+status_t CryptoHalAidl::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ bool isSupported = false;
+ Uuid uuidAidl = toAidlUuid(uuid);
+ std::vector<uint8_t> dataAidl = toStdVec(toVector(toHidlVec(data, size)));
+ for (size_t i = 0; i < mFactories.size(); i++) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuidAidl, &isSupported).isOk() && isSupported) {
+ mPlugin = makeCryptoPlugin(mFactories[i], uuidAidl, dataAidl);
+ // Reserve place for future plugins with new versions
+
+ break;
+ }
+ }
+
+ if (mInitCheck == NO_INIT) {
+ mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
+ }
+
+ return mInitCheck;
+}
+
+std::shared_ptr<ICryptoPluginAidl> CryptoHalAidl::makeCryptoPlugin(
+ const std::shared_ptr<ICryptoFactoryAidl>& factory, const Uuid& uuidAidl,
+ const std::vector<uint8_t> initData) {
+ std::shared_ptr<ICryptoPluginAidl> pluginAidl;
+ if (factory->createPlugin(uuidAidl, initData, &pluginAidl).isOk()) {
+ ALOGI("Create ICryptoPluginAidl. UUID:[%s]", uuidAidl.toString().c_str());
+ } else {
+ mInitCheck = DEAD_OBJECT;
+ ALOGE("Failed to create ICryptoPluginAidl. UUID:[%s]", uuidAidl.toString().c_str());
+ }
+
+ return pluginAidl;
+}
+
+status_t CryptoHalAidl::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ mPlugin.reset();
+ return OK;
+}
+
+bool CryptoHalAidl::requiresSecureDecoderComponent(const char* mime) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return false;
+ }
+
+ std::string mimeStr = std::string(mime);
+ bool result;
+ if (!mPlugin->requiresSecureDecoderComponent(mimeStr, &result).isOk()) {
+ ALOGE("Failed to requiresSecureDecoderComponent. mime:[%s]", mime);
+ return false;
+ }
+
+ return result;
+}
+
+void CryptoHalAidl::notifyResolution(uint32_t width, uint32_t height) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ // Check negative width and height after type conversion
+ // Log error and return if any is negative
+ if ((int32_t)width < 0 || (int32_t)height < 0) {
+ ALOGE("Negative width: %d or height %d in notifyResolution", width, height);
+ return;
+ }
+
+ ::ndk::ScopedAStatus status = mPlugin->notifyResolution(width, height);
+ if (!status.isOk()) {
+ ALOGE("notifyResolution txn failed status code: %d", status.getServiceSpecificError());
+ }
+}
+
+status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ auto err = mPlugin->setMediaDrmSession(toStdVec(sessionId));
+ return err.isOk() ? toStatusTAidl(err.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+ssize_t CryptoHalAidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern,
+ const SharedBufferHidl& hSource, size_t offset,
+ const CryptoPlugin::SubSample* subSamples, size_t numSubSamples,
+ const DestinationBufferHidl& hDestination, AString* errorDetailMsg) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ Mode aMode;
+ switch (mode) {
+ case CryptoPlugin::kMode_Unencrypted:
+ aMode = Mode::UNENCRYPTED;
+ break;
+ case CryptoPlugin::kMode_AES_CTR:
+ aMode = Mode::AES_CTR;
+ break;
+ case CryptoPlugin::kMode_AES_WV:
+ aMode = Mode::AES_CBC_CTS;
+ break;
+ case CryptoPlugin::kMode_AES_CBC:
+ aMode = Mode::AES_CBC;
+ break;
+ default:
+ return UNKNOWN_ERROR;
+ }
+
+ Pattern aPattern;
+ aPattern.encryptBlocks = pattern.mEncryptBlocks;
+ aPattern.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);
+ }
+
+ bool secure;
+ if (hDestination.type == BufferTypeHidl::SHARED_MEMORY) {
+ status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
+ if (status != OK) {
+ return status;
+ }
+ secure = false;
+ } else if (hDestination.type == BufferTypeHidl::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;
+ mLock.unlock();
+
+ std::vector<uint8_t> keyIdAidl = std::vector<uint8_t>(keyId, keyId + 16);
+ std::vector<uint8_t> ivAidl = std::vector<uint8_t>(iv, iv + 16);
+ DecryptResult result;
+ err = mPlugin->decrypt(secure, keyIdAidl, ivAidl, aMode, aPattern, stdSubSamples,
+ hidlSharedBufferToAidlSharedBuffer(hSource), offset,
+ hidlDestinationBufferToAidlDestinationBuffer(hDestination), &result)
+ .isOk()
+ ? OK
+ : DEAD_OBJECT;
+
+ *errorDetailMsg = toString8(result.detailedError);
+ if (err != OK) {
+ ALOGE("Failed on decrypt, error message:%s, bytes written:%d", result.detailedError.c_str(),
+ result.bytesWritten);
+ return err;
+ }
+
+ return result.bytesWritten;
+}
+
+int32_t CryptoHalAidl::setHeap(const sp<HidlMemory>& heap) {
+ if (heap == NULL || mHeapSeqNum < 0) {
+ ALOGE("setHeap(): 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());
+
+ Ashmem memAidl;
+ memAidl.fd.set(heap->handle()->data[0]);
+ memAidl.size = heap->size();
+
+ ALOGE_IF(!mPlugin->setSharedBufferBase(memAidl, bufferId).isOk(),
+ "setSharedBufferBase(): remote call failed");
+ return seqNum;
+}
+
+void CryptoHalAidl::unsetHeap(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);
+ Ashmem memAidl;
+ memAidl.fd.set(-1);
+ memAidl.size = 0;
+ ALOGE_IF(!mPlugin->setSharedBufferBase(memAidl, bufferId).isOk(),
+ "setSharedBufferBase(): remote call failed");
+ }
+ mHeapSizes.removeItem(seqNum);
+ }
+}
+
+status_t CryptoHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ // Need to convert logmessage
+
+ return DrmUtils::GetLogMessagesAidl<ICryptoPluginAidl>(mPlugin, logs);
+}
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/CryptoHalHidl.cpp b/drm/libmediadrm/CryptoHalHidl.cpp
new file mode 100644
index 0000000..cbb6ddf
--- /dev/null
+++ b/drm/libmediadrm/CryptoHalHidl.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CryptoHalHidl"
+#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/MediaErrors.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/CryptoHalHidl.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::sp;
+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;
+
+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());
+}
+
+CryptoHalHidl::CryptoHalHidl()
+ : mFactories(makeCryptoFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
+ mHeapSeqNum(0) {}
+
+CryptoHalHidl::~CryptoHalHidl() {}
+
+Vector<sp<ICryptoFactory>> CryptoHalHidl::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>& registered) {
+ 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>& registered) {
+ 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> CryptoHalHidl::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;
+}
+
+status_t CryptoHalHidl::initCheck() const {
+ return mInitCheck;
+}
+
+bool CryptoHalHidl::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;
+}
+
+status_t CryptoHalHidl::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 CryptoHalHidl::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ mPlugin.clear();
+ mPluginV1_2.clear();
+ return OK;
+}
+
+bool CryptoHalHidl::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 CryptoHalHidl::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 CryptoHalHidl::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 CryptoHalHidl::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 CryptoHalHidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern& pattern,
+ const drm::V1_0::SharedBuffer& hSource, size_t offset,
+ const CryptoPlugin::SubSample* subSamples, size_t numSubSamples,
+ const drm::V1_0::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;
+}
+
+void CryptoHalHidl::notifyResolution(uint32_t width, uint32_t height) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ auto hResult = mPlugin->notifyResolution(width, height);
+ ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
+}
+
+status_t CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId));
+ return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+}
+
+status_t CryptoHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs);
+}
+} // namespace android
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 40d1e0c..fe8b9f6 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -17,1557 +17,273 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmHal"
-#include <aidl/android/media/BnResourceManagerClient.h>
-#include <android/binder_manager.h>
-#include <android/hardware/drm/1.2/types.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-#include <media/EventMetric.h>
-#include <media/MediaMetrics.h>
-#include <media/PluginMetricsReporting.h>
-#include <media/drm/DrmAPI.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/base64.h>
-#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaErrors.h>
#include <mediadrm/DrmHal.h>
-#include <mediadrm/DrmSessionClientInterface.h>
-#include <mediadrm/DrmSessionManager.h>
-#include <mediadrm/IDrmMetricsConsumer.h>
+#include <mediadrm/DrmHalAidl.h>
+#include <mediadrm/DrmHalHidl.h>
#include <mediadrm/DrmUtils.h>
-#include <utils/Log.h>
-
-#include <iomanip>
-#include <vector>
-
-using drm::V1_0::KeyedVector;
-using drm::V1_0::KeyRequestType;
-using drm::V1_0::KeyType;
-using drm::V1_0::KeyValue;
-using drm::V1_0::SecureStop;
-using drm::V1_0::SecureStopId;
-using drm::V1_0::Status;
-using drm::V1_1::HdcpLevel;
-using drm::V1_1::SecureStopRelease;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeySetId;
-using drm::V1_2::KeyStatusType;
-using ::android::DrmUtils::toStatusT;
-using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::os::PersistableBundle;
-using ::android::sp;
-
-typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
-typedef drm::V1_2::Status Status_V1_2;
-typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
-
-namespace {
-
-// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
-// in the MediaDrm API.
-constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
-constexpr char kEqualsSign[] = "=";
-
-template<typename T>
-std::string toBase64StringNoPad(const T* data, size_t size) {
- // Note that the base 64 conversion only works with arrays of single-byte
- // values. If the source is empty or is not an array of single-byte values,
- // return empty string.
- if (size == 0 || sizeof(data[0]) != 1) {
- return "";
- }
-
- android::AString outputString;
- encodeBase64(data, size, &outputString);
- // Remove trailing equals padding if it exists.
- while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
- outputString.erase(outputString.size() - 1, 1);
- }
-
- return std::string(outputString.c_str(), outputString.size());
-}
-
-} // anonymous namespace
namespace android {
-#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
-
-static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
- Vector<uint8_t> vector;
- vector.appendArray(vec.data(), vec.size());
- return *const_cast<const Vector<uint8_t> *>(&vector);
+DrmHal::DrmHal() {
+ mDrmHalHidl = sp<DrmHalHidl>::make();
+ mDrmHalAidl = ndk::SharedRefBase::make<DrmHalAidl>();
}
-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 String8 toString8(const hidl_string &string) {
- return String8(string.c_str());
-}
-
-static hidl_string toHidlString(const String8& string) {
- return hidl_string(string.string());
-}
-
-static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
- switch(level) {
- case SecurityLevel::SW_SECURE_CRYPTO:
- return DrmPlugin::kSecurityLevelSwSecureCrypto;
- case SecurityLevel::SW_SECURE_DECODE:
- return DrmPlugin::kSecurityLevelSwSecureDecode;
- case SecurityLevel::HW_SECURE_CRYPTO:
- return DrmPlugin::kSecurityLevelHwSecureCrypto;
- case SecurityLevel::HW_SECURE_DECODE:
- return DrmPlugin::kSecurityLevelHwSecureDecode;
- case SecurityLevel::HW_SECURE_ALL:
- return DrmPlugin::kSecurityLevelHwSecureAll;
- default:
- return DrmPlugin::kSecurityLevelUnknown;
- }
-}
-
-static SecurityLevel toHidlSecurityLevel(DrmPlugin::SecurityLevel level) {
- switch(level) {
- case DrmPlugin::kSecurityLevelSwSecureCrypto:
- return SecurityLevel::SW_SECURE_CRYPTO;
- case DrmPlugin::kSecurityLevelSwSecureDecode:
- return SecurityLevel::SW_SECURE_DECODE;
- case DrmPlugin::kSecurityLevelHwSecureCrypto:
- return SecurityLevel::HW_SECURE_CRYPTO;
- case DrmPlugin::kSecurityLevelHwSecureDecode:
- return SecurityLevel::HW_SECURE_DECODE;
- case DrmPlugin::kSecurityLevelHwSecureAll:
- return SecurityLevel::HW_SECURE_ALL;
- default:
- return SecurityLevel::UNKNOWN;
- }
-}
-
-static DrmPlugin::OfflineLicenseState toOfflineLicenseState(
- OfflineLicenseState licenseState) {
- switch(licenseState) {
- case OfflineLicenseState::USABLE:
- return DrmPlugin::kOfflineLicenseStateUsable;
- case OfflineLicenseState::INACTIVE:
- return DrmPlugin::kOfflineLicenseStateReleased;
- default:
- return DrmPlugin::kOfflineLicenseStateUnknown;
- }
-}
-
-static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel_V1_2 level) {
- switch(level) {
- case HdcpLevel_V1_2::HDCP_NONE:
- return DrmPlugin::kHdcpNone;
- case HdcpLevel_V1_2::HDCP_V1:
- return DrmPlugin::kHdcpV1;
- case HdcpLevel_V1_2::HDCP_V2:
- return DrmPlugin::kHdcpV2;
- case HdcpLevel_V1_2::HDCP_V2_1:
- return DrmPlugin::kHdcpV2_1;
- case HdcpLevel_V1_2::HDCP_V2_2:
- return DrmPlugin::kHdcpV2_2;
- case HdcpLevel_V1_2::HDCP_V2_3:
- return DrmPlugin::kHdcpV2_3;
- case HdcpLevel_V1_2::HDCP_NO_OUTPUT:
- return DrmPlugin::kHdcpNoOutput;
- default:
- return DrmPlugin::kHdcpLevelUnknown;
- }
-}
-static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
- keyedVector) {
- std::vector<KeyValue> stdKeyedVector;
- for (size_t i = 0; i < keyedVector.size(); i++) {
- KeyValue keyValue;
- keyValue.key = toHidlString(keyedVector.keyAt(i));
- keyValue.value = toHidlString(keyedVector.valueAt(i));
- stdKeyedVector.push_back(keyValue);
- }
- return ::KeyedVector(stdKeyedVector);
-}
-
-static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
- hKeyedVector) {
- KeyedVector<String8, String8> keyedVector;
- for (size_t i = 0; i < hKeyedVector.size(); i++) {
- keyedVector.add(toString8(hKeyedVector[i].key),
- toString8(hKeyedVector[i].value));
- }
- return keyedVector;
-}
-
-static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
- hSecureStops) {
- List<Vector<uint8_t>> secureStops;
- for (size_t i = 0; i < hSecureStops.size(); i++) {
- secureStops.push_back(toVector(hSecureStops[i].opaqueData));
- }
- return secureStops;
-}
-
-static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
- hSecureStopIds) {
- List<Vector<uint8_t>> secureStopIds;
- for (size_t i = 0; i < hSecureStopIds.size(); i++) {
- secureStopIds.push_back(toVector(hSecureStopIds[i]));
- }
- return secureStopIds;
-}
-
-static List<Vector<uint8_t>> toKeySetIds(const hidl_vec<KeySetId>&
- hKeySetIds) {
- List<Vector<uint8_t>> keySetIds;
- for (size_t i = 0; i < hKeySetIds.size(); i++) {
- keySetIds.push_back(toVector(hKeySetIds[i]));
- }
- return keySetIds;
-}
-
-Mutex DrmHal::mLock;
-
-struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
- explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
- : mSessionId(sessionId),
- mDrm(drm) {}
-
- ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
- ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
-
- const Vector<uint8_t> mSessionId;
-
- virtual ~DrmSessionClient();
-
-private:
- wp<DrmHal> mDrm;
-
- DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
-};
-
-::ndk::ScopedAStatus DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
- auto sessionId = mSessionId;
- sp<DrmHal> drm = mDrm.promote();
- if (drm == NULL) {
- *_aidl_return = true;
- return ::ndk::ScopedAStatus::ok();
- }
- status_t err = drm->closeSession(sessionId);
- if (err != OK) {
- *_aidl_return = false;
- return ::ndk::ScopedAStatus::ok();
- }
- drm->sendEvent(EventType::SESSION_RECLAIMED,
- toHidlVec(sessionId), hidl_vec<uint8_t>());
- *_aidl_return = true;
- return ::ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
- String8 name;
- sp<DrmHal> drm = mDrm.promote();
- if (drm == NULL) {
- name.append("<deleted>");
- } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK
- || name.isEmpty()) {
- name.append("<Get vendor failed or is empty>");
- }
- name.append("[");
- for (size_t i = 0; i < mSessionId.size(); ++i) {
- name.appendFormat("%02x", mSessionId[i]);
- }
- name.append("]");
- *_aidl_return = name;
- return ::ndk::ScopedAStatus::ok();
-}
-
-DrmHal::DrmSessionClient::~DrmSessionClient() {
- DrmSessionManager::Instance()->removeSession(mSessionId);
-}
-
-DrmHal::DrmHal()
- : mFactories(makeDrmFactories()),
- mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
-}
-
-void DrmHal::closeOpenSessions() {
- Mutex::Autolock autoLock(mLock);
- auto openSessions = mOpenSessions;
- for (size_t i = 0; i < openSessions.size(); i++) {
- mLock.unlock();
- closeSession(openSessions[i]->mSessionId);
- mLock.lock();
- }
- mOpenSessions.clear();
-}
-
-DrmHal::~DrmHal() {
-}
-
-void DrmHal::cleanup() {
- closeOpenSessions();
-
- Mutex::Autolock autoLock(mLock);
- reportFrameworkMetrics(reportPluginMetrics());
-
- setListener(NULL);
- mInitCheck = NO_INIT;
- if (mPluginV1_2 != NULL) {
- if (!mPluginV1_2->setListener(NULL).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- } else if (mPlugin != NULL) {
- if (!mPlugin->setListener(NULL).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- }
- mPlugin.clear();
- mPluginV1_1.clear();
- mPluginV1_2.clear();
- mPluginV1_4.clear();
-}
-
-std::vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
- static std::vector<sp<IDrmFactory>> factories(DrmUtils::MakeDrmFactories());
- if (factories.size() == 0) {
- // must be in passthrough mode, load the default passthrough service
- auto passthrough = IDrmFactory::getService();
- if (passthrough != NULL) {
- DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
- factories.push_back(passthrough);
- } else {
- DrmUtils::LOG2BE("Failed to find any drm factories");
- }
- }
- return factories;
-}
-
-sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
- const uint8_t uuid[16], const String8& appPackageName) {
- mAppPackageName = appPackageName;
- mMetrics.SetAppPackageName(appPackageName);
- mMetrics.SetAppUid(AIBinder_getCallingUid());
-
- sp<IDrmPlugin> plugin;
- Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
- [&](Status status, const sp<IDrmPlugin>& hPlugin) {
- if (status != Status::OK) {
- DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
- return;
- }
- plugin = hPlugin;
- }
- );
-
- if (!hResult.isOk()) {
- DrmUtils::LOG2BE(uuid, "createPlugin remote call failed: %s",
- hResult.description().c_str());
- }
-
- return plugin;
-}
+DrmHal::~DrmHal() {}
status_t DrmHal::initCheck() const {
- return mInitCheck;
+ if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return OK;
+ if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT) return NO_INIT;
+ return mDrmHalHidl->initCheck();
}
-status_t DrmHal::setListener(const sp<IDrmClient>& listener)
-{
- Mutex::Autolock lock(mEventLock);
- mListener = listener;
- return NO_ERROR;
+status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result) {
+ status_t statusResult;
+ statusResult = mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+ if (*result) return statusResult;
+ return mDrmHalHidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
}
-Return<void> DrmHal::sendEvent(EventType hEventType,
- const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
- mMetrics.mEventCounter.Increment(hEventType);
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- DrmPlugin::EventType eventType;
- switch(hEventType) {
- case EventType::PROVISION_REQUIRED:
- eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
- break;
- case EventType::KEY_NEEDED:
- eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
- break;
- case EventType::KEY_EXPIRED:
- eventType = DrmPlugin::kDrmPluginEventKeyExpired;
- break;
- case EventType::VENDOR_DEFINED:
- eventType = DrmPlugin::kDrmPluginEventVendorDefined;
- break;
- case EventType::SESSION_RECLAIMED:
- eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
- break;
- default:
- return Void();
- }
- listener->sendEvent(eventType, sessionId, data);
- }
- return Void();
-}
-
-Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
- int64_t expiryTimeInMS) {
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
- }
- return Void();
-}
-
-Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus_V1_0>& keyStatusList_V1_0, bool hasNewUsableKey) {
- std::vector<KeyStatus> keyStatusVec;
- for (const auto &keyStatus_V1_0 : keyStatusList_V1_0) {
- keyStatusVec.push_back({keyStatus_V1_0.keyId,
- static_cast<KeyStatusType>(keyStatus_V1_0.type)});
- }
- hidl_vec<KeyStatus> keyStatusList_V1_2(keyStatusVec);
- return sendKeysChange_1_2(sessionId, keyStatusList_V1_2, hasNewUsableKey);
-}
-
-Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus>& hKeyStatusList, bool hasNewUsableKey) {
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- std::vector<DrmKeyStatus> keyStatusList;
- size_t nKeys = hKeyStatusList.size();
- for (size_t i = 0; i < nKeys; ++i) {
- const KeyStatus &keyStatus = hKeyStatusList[i];
- uint32_t type;
- switch(keyStatus.type) {
- case KeyStatusType::USABLE:
- type = DrmPlugin::kKeyStatusType_Usable;
- break;
- case KeyStatusType::EXPIRED:
- type = DrmPlugin::kKeyStatusType_Expired;
- break;
- case KeyStatusType::OUTPUTNOTALLOWED:
- type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
- break;
- case KeyStatusType::STATUSPENDING:
- type = DrmPlugin::kKeyStatusType_StatusPending;
- break;
- case KeyStatusType::USABLEINFUTURE:
- type = DrmPlugin::kKeyStatusType_UsableInFuture;
- break;
- case KeyStatusType::INTERNALERROR:
- default:
- type = DrmPlugin::kKeyStatusType_InternalError;
- break;
- }
- keyStatusList.push_back({type, keyStatus.keyId});
- mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
- }
-
- Mutex::Autolock lock(mNotifyLock);
- listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
- } else {
- // There's no listener. But we still want to count the key change
- // events.
- size_t nKeys = hKeyStatusList.size();
- for (size_t i = 0; i < nKeys; i++) {
- mMetrics.mKeyStatusChangeCounter.Increment(hKeyStatusList[i].type);
- }
- }
-
- return Void();
-}
-
-Return<void> DrmHal::sendSessionLostState(
- const hidl_vec<uint8_t>& sessionId) {
-
- mEventLock.lock();
- sp<IDrmClient> listener = mListener;
- mEventLock.unlock();
-
- if (listener != NULL) {
- Mutex::Autolock lock(mNotifyLock);
- listener->sendSessionLostState(sessionId);
- }
- return Void();
-}
-
-status_t DrmHal::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
- const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported) {
- *isSupported = false;
-
- // handle default value cases
- if (level == DrmPlugin::kSecurityLevelUnknown) {
- if (mimeType == "") {
- // isCryptoSchemeSupported(uuid)
- *isSupported = true;
- } else {
- // isCryptoSchemeSupported(uuid, mimeType)
- *isSupported = factory->isContentTypeSupported(mimeType.string());
- }
- return OK;
- } else if (mimeType == "") {
- return BAD_VALUE;
- }
-
- sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
- if (factoryV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- } else {
- *isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid,
- mimeType.string(), toHidlSecurityLevel(level));
- return OK;
- }
-}
-
-status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported) {
- Mutex::Autolock autoLock(mLock);
- *isSupported = false;
- for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
- if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
- return matchMimeTypeAndSecurityLevel(mFactories[i],
- uuid, mimeType, level, isSupported);
- }
- }
- return OK;
-}
-
-status_t DrmHal::createPlugin(const uint8_t uuid[16],
- const String8& appPackageName) {
- Mutex::Autolock autoLock(mLock);
-
- for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
- auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
- if (hResult.isOk() && hResult) {
- auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
- if (plugin != NULL) {
- mPlugin = plugin;
- mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
- mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
- mPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mPlugin);
- break;
- }
- }
- }
-
- if (mPlugin == NULL) {
- DrmUtils::LOG2BE(uuid, "No supported hal instance found");
- mInitCheck = ERROR_UNSUPPORTED;
- } else {
- mInitCheck = OK;
- if (mPluginV1_2 != NULL) {
- if (!mPluginV1_2->setListener(this).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- } else if (!mPlugin->setListener(this).isOk()) {
- mInitCheck = DEAD_OBJECT;
- }
- if (mInitCheck != OK) {
- mPlugin.clear();
- mPluginV1_1.clear();
- mPluginV1_2.clear();
- mPluginV1_4.clear();
- }
- }
-
-
- return mInitCheck;
+status_t DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ status_t statusResult;
+ statusResult = mDrmHalAidl->createPlugin(uuid, appPackageName);
+ if (statusResult != OK) return mDrmHalHidl->createPlugin(uuid, appPackageName);
+ return statusResult;
}
status_t DrmHal::destroyPlugin() {
- cleanup();
- return OK;
+ status_t statusResult = mDrmHalAidl->destroyPlugin();
+ status_t statusResultHidl = mDrmHalHidl->destroyPlugin();
+ if (statusResult != OK) return statusResult;
+ return statusResultHidl;
}
-status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
- Vector<uint8_t> &sessionId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- SecurityLevel hSecurityLevel = toHidlSecurityLevel(level);
- bool setSecurityLevel = true;
-
- if (level == DrmPlugin::kSecurityLevelMax) {
- setSecurityLevel = false;
- } else {
- if (hSecurityLevel == SecurityLevel::UNKNOWN) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
- }
-
- status_t err = UNKNOWN_ERROR;
- bool retry = true;
- do {
- hidl_vec<uint8_t> hSessionId;
-
- Return<void> hResult;
- if (mPluginV1_1 == NULL || !setSecurityLevel) {
- hResult = mPlugin->openSession(
- [&](Status status,const hidl_vec<uint8_t>& id) {
- if (status == Status::OK) {
- sessionId = toVector(id);
- }
- err = toStatusT(status);
- }
- );
- } else {
- hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
- [&](Status status, const hidl_vec<uint8_t>& id) {
- if (status == Status::OK) {
- sessionId = toVector(id);
- }
- err = toStatusT(status);
- }
- );
- }
-
- if (!hResult.isOk()) {
- err = DEAD_OBJECT;
- }
-
- if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
- mLock.unlock();
- // reclaimSession may call back to closeSession, since mLock is
- // shared between Drm instances, we should unlock here to avoid
- // deadlock.
- retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
- mLock.lock();
- } else {
- retry = false;
- }
- } while (retry);
-
- if (err == OK) {
- std::shared_ptr<DrmSessionClient> client =
- ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
- DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
- std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
- mOpenSessions.push_back(client);
- mMetrics.SetSessionStart(sessionId);
- }
-
- mMetrics.mOpenSessionCounter.Increment(err);
- return err;
+status_t DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->openSession(securityLevel, sessionId);
+ return mDrmHalHidl->openSession(securityLevel, sessionId);
}
-status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
- if (status.isOk()) {
- if (status == Status::OK) {
- DrmSessionManager::Instance()->removeSession(sessionId);
- for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
- if (isEqualSessionId((*i)->mSessionId, sessionId)) {
- mOpenSessions.erase(i);
- break;
- }
- }
- }
- status_t response = toStatusT(status);
- mMetrics.SetSessionEnd(sessionId);
- mMetrics.mCloseSessionCounter.Increment(response);
- return response;
- }
- mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
- return DEAD_OBJECT;
+status_t DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->closeSession(sessionId);
+ return mDrmHalHidl->closeSession(sessionId);
}
-static DrmPlugin::KeyRequestType toKeyRequestType(
- KeyRequestType keyRequestType) {
- switch (keyRequestType) {
- case KeyRequestType::INITIAL:
- return DrmPlugin::kKeyRequestType_Initial;
- break;
- case KeyRequestType::RENEWAL:
- return DrmPlugin::kKeyRequestType_Renewal;
- break;
- case KeyRequestType::RELEASE:
- return DrmPlugin::kKeyRequestType_Release;
- break;
- default:
- return DrmPlugin::kKeyRequestType_Unknown;
- break;
- }
+status_t DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
+ String8 const& mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getKeyRequest(sessionId, initData, mimeType, keyType,
+ optionalParameters, request, defaultUrl, keyRequestType);
+ return mDrmHalHidl->getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters,
+ request, defaultUrl, keyRequestType);
}
-static DrmPlugin::KeyRequestType toKeyRequestType_1_1(
- KeyRequestType_V1_1 keyRequestType) {
- switch (keyRequestType) {
- case KeyRequestType_V1_1::NONE:
- return DrmPlugin::kKeyRequestType_None;
- break;
- case KeyRequestType_V1_1::UPDATE:
- return DrmPlugin::kKeyRequestType_Update;
- break;
- default:
- return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType));
- break;
- }
+status_t DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->provideKeyResponse(sessionId, response, keySetId);
+ return mDrmHalHidl->provideKeyResponse(sessionId, response, keySetId);
}
-status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &initData, String8 const &mimeType,
- DrmPlugin::KeyType keyType, KeyedVector<String8,
- String8> const &optionalParameters, Vector<uint8_t> &request,
- String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
- EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- KeyType hKeyType;
- if (keyType == DrmPlugin::kKeyType_Streaming) {
- hKeyType = KeyType::STREAMING;
- } else if (keyType == DrmPlugin::kKeyType_Offline) {
- hKeyType = KeyType::OFFLINE;
- } else if (keyType == DrmPlugin::kKeyType_Release) {
- hKeyType = KeyType::RELEASE;
- } else {
- keyRequestTimer.SetAttribute(BAD_VALUE);
- return BAD_VALUE;
- }
-
- ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
-
- status_t err = UNKNOWN_ERROR;
- Return<void> hResult;
-
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->getKeyRequest_1_2(
- toHidlVec(sessionId), toHidlVec(initData),
- toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType_V1_1 hKeyRequestType,
- const hidl_string& hDefaultUrl) {
- if (status == Status_V1_2::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
- }
- err = toStatusT(status);
- });
- } else if (mPluginV1_1 != NULL) {
- hResult = mPluginV1_1->getKeyRequest_1_1(
- toHidlVec(sessionId), toHidlVec(initData),
- toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType_V1_1 hKeyRequestType,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
- }
- err = toStatusT(status);
- });
- } else {
- hResult = mPlugin->getKeyRequest(
- toHidlVec(sessionId), toHidlVec(initData),
- toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- KeyRequestType hKeyRequestType,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- *keyRequestType = toKeyRequestType(hKeyRequestType);
- }
- err = toStatusT(status);
- });
- }
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- keyRequestTimer.SetAttribute(err);
- return err;
+status_t DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeKeys(keySetId);
+ return mDrmHalHidl->removeKeys(keySetId);
}
-status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
- EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
- toHidlVec(response),
- [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
- if (status == Status::OK) {
- keySetId = toVector(hKeySetId);
- }
- err = toStatusT(status);
- }
- );
- err = hResult.isOk() ? err : DEAD_OBJECT;
- keyResponseTimer.SetAttribute(err);
- return err;
+status_t DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->restoreKeys(sessionId, keySetId);
+ return mDrmHalHidl->restoreKeys(sessionId, keySetId);
}
-status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->queryKeyStatus(sessionId, infoMap);
+ return mDrmHalHidl->queryKeyStatus(sessionId, infoMap);
}
-status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
- toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
+ return mDrmHalHidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
}
-status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- ::KeyedVector hInfoMap;
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
- [&](Status status, const hidl_vec<KeyValue>& map) {
- if (status == Status::OK) {
- infoMap = toKeyedVector(map);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->provideProvisionResponse(response, certificate, wrappedKey);
+ return mDrmHalHidl->provideProvisionResponse(response, certificate, wrappedKey);
}
-status_t DrmHal::getProvisionRequest(String8 const &certType,
- String8 const &certAuthority, Vector<uint8_t> &request,
- String8 &defaultUrl) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
- Return<void> hResult;
-
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->getProvisionRequest_1_2(
- toHidlString(certType), toHidlString(certAuthority),
- [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
- const hidl_string& hDefaultUrl) {
- if (status == Status_V1_2::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- }
- err = toStatusT(status);
- }
- );
- } else {
- hResult = mPlugin->getProvisionRequest(
- toHidlString(certType), toHidlString(certAuthority),
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
- }
- err = toStatusT(status);
- }
- );
- }
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- mMetrics.mGetProvisionRequestCounter.Increment(err);
- return err;
+status_t DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStops(secureStops);
+ return mDrmHalHidl->getSecureStops(secureStops);
}
-status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
- [&](Status status, const hidl_vec<uint8_t>& hCertificate,
- const hidl_vec<uint8_t>& hWrappedKey) {
- if (status == Status::OK) {
- certificate = toVector(hCertificate);
- wrappedKey = toVector(hWrappedKey);
- }
- err = toStatusT(status);
- }
- );
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- mMetrics.mProvideProvisionResponseCounter.Increment(err);
- return err;
+status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStopIds(secureStopIds);
+ return mDrmHalHidl->getSecureStopIds(secureStopIds);
}
-status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getSecureStops(
- [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
- if (status == Status::OK) {
- secureStops = toSecureStops(hSecureStops);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStop(ssid, secureStop);
+ return mDrmHalHidl->getSecureStop(ssid, secureStop);
}
-
-status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPluginV1_1->getSecureStopIds(
- [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
- if (status == Status::OK) {
- secureStopIds = toSecureStopIds(hSecureStopIds);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->releaseSecureStops(ssRelease);
+ return mDrmHalHidl->releaseSecureStops(ssRelease);
}
-
-status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
- [&](Status status, const SecureStop& hSecureStop) {
- if (status == Status::OK) {
- secureStop = toVector(hSecureStop.opaqueData);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
-}
-
-status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status(Status::ERROR_DRM_UNKNOWN);
- if (mPluginV1_1 != NULL) {
- SecureStopRelease secureStopRelease;
- secureStopRelease.opaqueData = toHidlVec(ssRelease);
- status = mPluginV1_1->releaseSecureStops(secureStopRelease);
- } else {
- status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
- }
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
-}
-
-status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeSecureStop(ssid);
+ return mDrmHalHidl->removeSecureStop(ssid);
}
status_t DrmHal::removeAllSecureStops() {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status(Status::ERROR_DRM_UNKNOWN);
- if (mPluginV1_1 != NULL) {
- status = mPluginV1_1->removeAllSecureStops();
- } else {
- status = mPlugin->releaseAllSecureStops();
- }
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeAllSecureStops();
+ return mDrmHalHidl->removeAllSecureStops();
}
-status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
- DrmPlugin::HdcpLevel *max) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- if (connected == NULL || max == NULL) {
- return BAD_VALUE;
- }
- status_t err = UNKNOWN_ERROR;
-
- *connected = DrmPlugin::kHdcpLevelUnknown;
- *max = DrmPlugin::kHdcpLevelUnknown;
-
- Return<void> hResult;
- if (mPluginV1_2 != NULL) {
- hResult = mPluginV1_2->getHdcpLevels_1_2(
- [&](Status_V1_2 status, const HdcpLevel_V1_2& hConnected, const HdcpLevel_V1_2& hMax) {
- if (status == Status_V1_2::OK) {
- *connected = toHdcpLevel(hConnected);
- *max = toHdcpLevel(hMax);
- }
- err = toStatusT(status);
- });
- } else if (mPluginV1_1 != NULL) {
- hResult = mPluginV1_1->getHdcpLevels(
- [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
- if (status == Status::OK) {
- *connected = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hConnected));
- *max = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hMax));
- }
- err = toStatusT(status);
- });
- } else {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getHdcpLevels(connectedLevel, maxLevel);
+ return mDrmHalHidl->getHdcpLevels(connectedLevel, maxLevel);
}
-status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- if (open == NULL || max == NULL) {
- return BAD_VALUE;
- }
- status_t err = UNKNOWN_ERROR;
-
- *open = 0;
- *max = 0;
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<void> hResult = mPluginV1_1->getNumberOfSessions(
- [&](Status status, uint32_t hOpen, uint32_t hMax) {
- if (status == Status::OK) {
- *open = hOpen;
- *max = hMax;
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getNumberOfSessions(currentSessions, maxSessions);
+ return mDrmHalHidl->getNumberOfSessions(currentSessions, maxSessions);
}
-status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
- DrmPlugin::SecurityLevel *level) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- if (level == NULL) {
- return BAD_VALUE;
- }
- status_t err = UNKNOWN_ERROR;
-
- if (mPluginV1_1 == NULL) {
- return ERROR_DRM_CANNOT_HANDLE;
- }
-
- *level = DrmPlugin::kSecurityLevelUnknown;
-
- Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
- [&](Status status, SecurityLevel hLevel) {
- if (status == Status::OK) {
- *level = toSecurityLevel(hLevel);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecurityLevel(sessionId, level);
+ return mDrmHalHidl->getSecurityLevel(sessionId, level);
}
-status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- }
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
- [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
- if (status == Status::OK) {
- keySetIds = toKeySetIds(hKeySetIds);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getOfflineLicenseKeySetIds(keySetIds);
+ return mDrmHalHidl->getOfflineLicenseKeySetIds(keySetIds);
}
-status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const &keySetId) {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- }
-
- Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeOfflineLicense(keySetId);
+ return mDrmHalHidl->removeOfflineLicense(keySetId);
}
-status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const &keySetId,
- DrmPlugin::OfflineLicenseState *licenseState) const {
- Mutex::Autolock autoLock(mLock);
-
- if (mInitCheck != OK) {
- return mInitCheck;
- }
-
- if (mPluginV1_2 == NULL) {
- return ERROR_UNSUPPORTED;
- }
- *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPluginV1_2->getOfflineLicenseState(toHidlVec(keySetId),
- [&](Status status, OfflineLicenseState hLicenseState) {
- if (status == Status::OK) {
- *licenseState = toOfflineLicenseState(hLicenseState);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->getOfflineLicenseState(keySetId, licenseState);
+ return mDrmHalHidl->getOfflineLicenseState(keySetId, licenseState);
}
-status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
- Mutex::Autolock autoLock(mLock);
- return getPropertyStringInternal(name, value);
+status_t DrmHal::getPropertyString(String8 const& name, String8& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyString(name, value);
+ return mDrmHalHidl->getPropertyString(name, value);
}
-status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
- // This function is internal to the class and should only be called while
- // mLock is already held.
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
- [&](Status status, const hidl_string& hValue) {
- if (status == Status::OK) {
- value = toString8(hValue);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyByteArray(name, value);
+ return mDrmHalHidl->getPropertyByteArray(name, value);
}
-status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
- Mutex::Autolock autoLock(mLock);
- return getPropertyByteArrayInternal(name, value);
+status_t DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyString(name, value);
+ return mDrmHalHidl->setPropertyString(name, value);
}
-status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
- // This function is internal to the class and should only be called while
- // mLock is already held.
- INIT_CHECK();
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
- [&](Status status, const hidl_vec<uint8_t>& hValue) {
- if (status == Status::OK) {
- value = toVector(hValue);
- }
- err = toStatusT(status);
- }
- );
-
- err = hResult.isOk() ? err : DEAD_OBJECT;
- if (name == kPropertyDeviceUniqueId) {
- mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
- }
- return err;
+status_t DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyByteArray(name, value);
+ return mDrmHalHidl->setPropertyByteArray(name, value);
}
-status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
- toHidlString(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getMetrics(consumer);
+ return mDrmHalHidl->getMetrics(consumer);
}
-status_t DrmHal::setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
- toHidlVec(value));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->setCipherAlgorithm(sessionId, algorithm);
+ return mDrmHalHidl->setCipherAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer> &consumer) {
- if (consumer == nullptr) {
- return UNEXPECTED_NULL;
- }
- consumer->consumeFrameworkMetrics(mMetrics);
-
- // Append vendor metrics if they are supported.
- if (mPluginV1_1 != NULL) {
- String8 vendor;
- String8 description;
- if (getPropertyStringInternal(String8("vendor"), vendor) != OK
- || vendor.isEmpty()) {
- ALOGE("Get vendor failed or is empty");
- vendor = "NONE";
- }
- if (getPropertyStringInternal(String8("description"), description) != OK
- || description.isEmpty()) {
- ALOGE("Get description failed or is empty.");
- description = "NONE";
- }
- vendor += ".";
- vendor += description;
-
- hidl_vec<DrmMetricGroup> pluginMetrics;
- status_t err = UNKNOWN_ERROR;
-
- Return<void> status = mPluginV1_1->getMetrics(
- [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
- if (status != Status::OK) {
- ALOGV("Error getting plugin metrics: %d", status);
- } else {
- consumer->consumeHidlMetrics(vendor, pluginMetrics);
- }
- err = toStatusT(status);
- });
- return status.isOk() ? err : DEAD_OBJECT;
- }
-
- return OK;
+status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setMacAlgorithm(sessionId, algorithm);
+ return mDrmHalHidl->setMacAlgorithm(sessionId, algorithm);
}
-status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- Return<Status> status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
- toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->encrypt(sessionId, keyId, input, iv, output);
+ return mDrmHalHidl->encrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
- toHidlString(algorithm));
- return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+status_t DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->decrypt(sessionId, keyId, input, iv, output);
+ return mDrmHalHidl->decrypt(sessionId, keyId, input, iv, output);
}
-status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
- toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
- [&](Status status, const hidl_vec<uint8_t>& hOutput) {
- if (status == Status::OK) {
- output = toVector(hOutput);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->sign(sessionId, keyId, message, signature);
+ return mDrmHalHidl->sign(sessionId, keyId, message, signature);
}
-status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
- toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
- [&](Status status, const hidl_vec<uint8_t>& hOutput) {
- if (status == Status::OK) {
- output = toVector(hOutput);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->verify(sessionId, keyId, message, signature, match);
+ return mDrmHalHidl->verify(sessionId, keyId, message, signature, match);
}
-status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
- Vector<uint8_t> &signature) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
- toHidlVec(keyId), toHidlVec(message),
- [&](Status status, const hidl_vec<uint8_t>& hSignature) {
- if (status == Status::OK) {
- signature = toVector(hSignature);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+ return mDrmHalHidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
}
-status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature, bool &match) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
- toHidlVec(message), toHidlVec(signature),
- [&](Status status, bool hMatch) {
- if (status == Status::OK) {
- match = hMatch;
- } else {
- match = false;
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::setListener(const sp<IDrmClient>& listener) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setListener(listener);
+ return mDrmHalHidl->setListener(listener);
}
-status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm, Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
- Mutex::Autolock autoLock(mLock);
- INIT_CHECK();
-
- DrmSessionManager::Instance()->useSession(sessionId);
-
- status_t err = UNKNOWN_ERROR;
-
- Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
- toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
- [&](Status status, const hidl_vec<uint8_t>& hSignature) {
- if (status == Status::OK) {
- signature = toVector(hSignature);
- }
- err = toStatusT(status);
- }
- );
-
- return hResult.isOk() ? err : DEAD_OBJECT;
+status_t DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->requiresSecureDecoder(mime, required);
+ return mDrmHalHidl->requiresSecureDecoder(mime, required);
}
-std::string DrmHal::reportFrameworkMetrics(const std::string& pluginMetrics) const
-{
- mediametrics_handle_t item(mediametrics_create("mediadrm"));
- mediametrics_setUid(item, mMetrics.GetAppUid());
- String8 vendor;
- String8 description;
- status_t result = getPropertyStringInternal(String8("vendor"), vendor);
- if (result != OK) {
- ALOGE("Failed to get vendor from drm plugin: %d", result);
- } else {
- mediametrics_setCString(item, "vendor", vendor.c_str());
- }
- result = getPropertyStringInternal(String8("description"), description);
- if (result != OK) {
- ALOGE("Failed to get description from drm plugin: %d", result);
- } else {
- mediametrics_setCString(item, "description", description.c_str());
- }
-
- std::string serializedMetrics;
- result = mMetrics.GetSerializedMetrics(&serializedMetrics);
- if (result != OK) {
- ALOGE("Failed to serialize framework metrics: %d", result);
- }
- std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
- serializedMetrics.size());
- if (!b64EncodedMetrics.empty()) {
- mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
- }
- if (!pluginMetrics.empty()) {
- mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str());
- }
- if (!mediametrics_selfRecord(item)) {
- ALOGE("Failed to self record framework metrics");
- }
- mediametrics_delete(item);
- return serializedMetrics;
+status_t DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ if (mDrmHalAidl->initCheck() == OK)
+ return mDrmHalAidl->requiresSecureDecoder(mime, securityLevel, required);
+ return mDrmHalHidl->requiresSecureDecoder(mime, securityLevel, required);
}
-std::string DrmHal::reportPluginMetrics() const
-{
- Vector<uint8_t> metricsVector;
- String8 vendor;
- String8 description;
- std::string metricsString;
- if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
- getPropertyStringInternal(String8("description"), description) == OK &&
- getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
- metricsString = toBase64StringNoPad(metricsVector.array(),
- metricsVector.size());
- status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
- description, mMetrics.GetAppUid());
- if (res != OK) {
- ALOGE("Metrics were retrieved but could not be reported: %d", res);
- }
- }
- return metricsString;
+status_t DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPlaybackId(sessionId, playbackId);
+ return mDrmHalHidl->setPlaybackId(sessionId, playbackId);
}
-status_t DrmHal::requiresSecureDecoder(const char *mime, bool *required) const {
- Mutex::Autolock autoLock(mLock);
- if (mPluginV1_4 == NULL) {
- return false;
- }
- auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
- if (!hResult.isOk()) {
- DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
- }
- if (required) {
- *required = hResult;
- }
- return OK;
-}
-
-status_t DrmHal::requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
- bool *required) const {
- Mutex::Autolock autoLock(mLock);
- if (mPluginV1_4 == NULL) {
- return false;
- }
- auto hLevel = toHidlSecurityLevel(securityLevel);
- auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
- if (!hResult.isOk()) {
- DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
- return DEAD_OBJECT;
- }
- if (required) {
- *required = hResult;
- }
- return OK;
-}
-
-status_t DrmHal::setPlaybackId(Vector<uint8_t> const &sessionId, const char *playbackId) {
- Mutex::Autolock autoLock(mLock);
- if (mPluginV1_4 == NULL) {
- return ERROR_UNSUPPORTED;
- }
- auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
- return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
-}
-
-status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const {
- Mutex::Autolock autoLock(mLock);
- return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getLogMessages(logs);
+ return mDrmHalHidl->getLogMessages(logs);
}
} // namespace android
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
new file mode 100644
index 0000000..7df57a3
--- /dev/null
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -0,0 +1,1326 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "DrmHalAidl"
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <media/PluginMetricsReporting.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/DrmHalAidl.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmUtils.h>
+
+using ::android::DrmUtils::toStatusTAidl;
+
+using ::aidl::android::hardware::drm::DrmMetricNamedValue;
+using ::aidl::android::hardware::drm::DrmMetricValue;
+using ::aidl::android::hardware::drm::HdcpLevel;
+using ::aidl::android::hardware::drm::HdcpLevels;
+using ::aidl::android::hardware::drm::KeyRequest;
+using ::aidl::android::hardware::drm::KeyRequestType;
+using ::aidl::android::hardware::drm::KeySetId;
+using ::aidl::android::hardware::drm::KeyStatus;
+using ::aidl::android::hardware::drm::KeyStatusType;
+using ::aidl::android::hardware::drm::KeyType;
+using ::aidl::android::hardware::drm::KeyValue;
+using ::aidl::android::hardware::drm::NumberOfSessions;
+using ::aidl::android::hardware::drm::OfflineLicenseState;
+using ::aidl::android::hardware::drm::OpaqueData;
+using ::aidl::android::hardware::drm::ProvideProvisionResponseResult;
+using ::aidl::android::hardware::drm::ProvisionRequest;
+using ::aidl::android::hardware::drm::SecureStop;
+using ::aidl::android::hardware::drm::SecureStopId;
+using ::aidl::android::hardware::drm::SecurityLevel;
+using ::aidl::android::hardware::drm::Status;
+using ::aidl::android::hardware::drm::Uuid;
+using DrmMetricGroupAidl = ::aidl::android::hardware::drm::DrmMetricGroup;
+using DrmMetricGroupHidl = ::android::hardware::drm::V1_1::DrmMetricGroup;
+using DrmMetricAidl = ::aidl::android::hardware::drm::DrmMetric;
+using DrmMetricHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Metric;
+using ValueHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Value;
+using AttributeHidl = ::android::hardware::drm::V1_1::DrmMetricGroup::Attribute;
+using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
+using EventTypeAidl = ::aidl::android::hardware::drm::EventType;
+using KeyStatusAidl = ::aidl::android::hardware::drm::KeyStatus;
+using ::android::hardware::hidl_vec;
+
+namespace {
+
+constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
+constexpr char kEqualsSign[] = "=";
+
+template <typename T>
+std::string toBase64StringNoPad(const T* data, size_t size) {
+ // Note that the base 64 conversion only works with arrays of single-byte
+ // values. If the source is empty or is not an array of single-byte values,
+ // return empty string.
+ if (size == 0 || sizeof(data[0]) != 1) {
+ return "";
+ }
+
+ android::AString outputString;
+ encodeBase64(data, size, &outputString);
+ // Remove trailing equals padding if it exists.
+ while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
+ outputString.erase(outputString.size() - 1, 1);
+ }
+
+ return std::string(outputString.c_str(), outputString.size());
+}
+
+} // anonymous namespace
+
+namespace android {
+
+#define INIT_CHECK() \
+ { \
+ if (mInitCheck != OK) return mInitCheck; \
+ }
+
+static Uuid toAidlUuid(const uint8_t* uuid) {
+ Uuid uuidAidl;
+ uuidAidl.uuid = std::vector<uint8_t>(uuid, uuid + 16);
+ return uuidAidl;
+}
+
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t>& vector) {
+ auto v = reinterpret_cast<const Byte*>(vector.array());
+ std::vector<Byte> vec(v, v + vector.size());
+ return vec;
+}
+
+static const Vector<uint8_t> toVector(const std::vector<uint8_t>& vec) {
+ Vector<uint8_t> vector;
+ vector.appendArray(vec.data(), vec.size());
+ return *const_cast<const Vector<uint8_t>*>(&vector);
+}
+
+static String8 toString8(const std::string& string) {
+ return String8(string.c_str());
+}
+
+static std::string toStdString(const String8& string8) {
+ return std::string(string8.string());
+}
+
+static std::vector<KeyValue> toKeyValueVector(const KeyedVector<String8, String8>& keyedVector) {
+ std::vector<KeyValue> stdKeyedVector;
+ for (size_t i = 0; i < keyedVector.size(); i++) {
+ KeyValue keyValue;
+ keyValue.key = toStdString(keyedVector.keyAt(i));
+ keyValue.value = toStdString(keyedVector.valueAt(i));
+ stdKeyedVector.push_back(keyValue);
+ }
+ return stdKeyedVector;
+}
+
+static KeyedVector<String8, String8> toKeyedVector(const std::vector<KeyValue>& keyValueVec) {
+ KeyedVector<String8, String8> keyedVector;
+ for (size_t i = 0; i < keyValueVec.size(); i++) {
+ keyedVector.add(toString8(keyValueVec[i].key), toString8(keyValueVec[i].value));
+ }
+ return keyedVector;
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType::INITIAL:
+ return DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case KeyRequestType::RENEWAL:
+ return DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case KeyRequestType::RELEASE:
+ return DrmPlugin::kKeyRequestType_Release;
+ break;
+ case KeyRequestType::NONE:
+ return DrmPlugin::kKeyRequestType_None;
+ break;
+ case KeyRequestType::UPDATE:
+ return DrmPlugin::kKeyRequestType_Update;
+ break;
+ default:
+ return DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+}
+
+static List<Vector<uint8_t>> toSecureStops(const std::vector<SecureStop>& aSecureStops) {
+ List<Vector<uint8_t>> secureStops;
+ for (size_t i = 0; i < aSecureStops.size(); i++) {
+ secureStops.push_back(toVector(aSecureStops[i].opaqueData));
+ }
+ return secureStops;
+}
+
+static List<Vector<uint8_t>> toSecureStopIds(const std::vector<SecureStopId>& aSecureStopIds) {
+ List<Vector<uint8_t>> secureStopIds;
+ for (size_t i = 0; i < aSecureStopIds.size(); i++) {
+ secureStopIds.push_back(toVector(aSecureStopIds[i].secureStopId));
+ }
+ return secureStopIds;
+}
+
+static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
+ switch (level) {
+ case HdcpLevel::HDCP_NONE:
+ return DrmPlugin::kHdcpNone;
+ case HdcpLevel::HDCP_V1:
+ return DrmPlugin::kHdcpV1;
+ case HdcpLevel::HDCP_V2:
+ return DrmPlugin::kHdcpV2;
+ case HdcpLevel::HDCP_V2_1:
+ return DrmPlugin::kHdcpV2_1;
+ case HdcpLevel::HDCP_V2_2:
+ return DrmPlugin::kHdcpV2_2;
+ case HdcpLevel::HDCP_V2_3:
+ return DrmPlugin::kHdcpV2_3;
+ case HdcpLevel::HDCP_NO_OUTPUT:
+ return DrmPlugin::kHdcpNoOutput;
+ default:
+ return DrmPlugin::kHdcpLevelUnknown;
+ }
+}
+
+static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
+ switch (level) {
+ case SecurityLevel::SW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelSwSecureCrypto;
+ case SecurityLevel::SW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelSwSecureDecode;
+ case SecurityLevel::HW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelHwSecureCrypto;
+ case SecurityLevel::HW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelHwSecureDecode;
+ case SecurityLevel::HW_SECURE_ALL:
+ return DrmPlugin::kSecurityLevelHwSecureAll;
+ case SecurityLevel::DEFAULT:
+ return DrmPlugin::kSecurityLevelMax;
+ default:
+ return DrmPlugin::kSecurityLevelUnknown;
+ }
+}
+
+static SecurityLevel toAidlSecurityLevel(DrmPlugin::SecurityLevel level) {
+ switch (level) {
+ case DrmPlugin::kSecurityLevelSwSecureCrypto:
+ return SecurityLevel::SW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelSwSecureDecode:
+ return SecurityLevel::SW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureCrypto:
+ return SecurityLevel::HW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelHwSecureDecode:
+ return SecurityLevel::HW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureAll:
+ return SecurityLevel::HW_SECURE_ALL;
+ case DrmPlugin::kSecurityLevelMax:
+ return SecurityLevel::DEFAULT;
+ default:
+ return SecurityLevel::UNKNOWN;
+ }
+}
+
+static List<Vector<uint8_t>> toKeySetIds(const std::vector<KeySetId>& hKeySetIds) {
+ List<Vector<uint8_t>> keySetIds;
+ for (size_t i = 0; i < hKeySetIds.size(); i++) {
+ keySetIds.push_back(toVector(hKeySetIds[i].keySetId));
+ }
+ return keySetIds;
+}
+
+static DrmPlugin::OfflineLicenseState toOfflineLicenseState(OfflineLicenseState licenseState) {
+ switch (licenseState) {
+ case OfflineLicenseState::USABLE:
+ return DrmPlugin::kOfflineLicenseStateUsable;
+ case OfflineLicenseState::INACTIVE:
+ return DrmPlugin::kOfflineLicenseStateReleased;
+ default:
+ return DrmPlugin::kOfflineLicenseStateUnknown;
+ }
+}
+
+template <typename T = uint8_t>
+static hidl_vec<T> toHidlVec(const Vector<T>& vector) {
+ hidl_vec<T> vec;
+ vec.setToExternal(const_cast<T*>(vector.array()), vector.size());
+ return vec;
+}
+
+Mutex DrmHalAidl::mLock;
+
+static hidl_vec<DrmMetricGroupHidl> toDrmMetricGroupHidl(std::vector<DrmMetricGroupAidl> result) {
+ Vector<DrmMetricGroupHidl> resultHidl;
+ for (auto r : result) {
+ DrmMetricGroupHidl re;
+ Vector<DrmMetricHidl> tmpMetric;
+ for (auto m : r.metrics) {
+ DrmMetricHidl me;
+ me.name = m.name;
+ Vector<AttributeHidl> aTmp;
+ for (auto attr : m.attributes) {
+ AttributeHidl attrHidl;
+ attrHidl.name = attr.name;
+
+ switch (attr.value.getTag()) {
+ case DrmMetricValue::Tag::int64Value:
+ attrHidl.type = DrmMetricGroupHidl::ValueType::INT64_TYPE;
+ attrHidl.int64Value = attr.value.get<DrmMetricValue::Tag::int64Value>();
+ break;
+ case DrmMetricValue::Tag::doubleValue:
+ attrHidl.type = DrmMetricGroupHidl::ValueType::DOUBLE_TYPE;
+ attrHidl.doubleValue = attr.value.get<DrmMetricValue::Tag::doubleValue>();
+ break;
+ case DrmMetricValue::Tag::stringValue:
+ attrHidl.type = DrmMetricGroupHidl::ValueType::STRING_TYPE;
+ attrHidl.stringValue = attr.value.get<DrmMetricValue::Tag::stringValue>();
+ break;
+ default:
+ break;
+ }
+
+ aTmp.push_back(attrHidl);
+ }
+
+ me.attributes = toHidlVec<AttributeHidl>(aTmp);
+
+ Vector<ValueHidl> vTmp;
+ for (auto value : m.values) {
+ ValueHidl valueHidl;
+ valueHidl.componentName = value.name;
+ switch (value.value.getTag()) {
+ case DrmMetricValue::Tag::int64Value:
+ valueHidl.type = DrmMetricGroupHidl::ValueType::INT64_TYPE;
+ valueHidl.int64Value = value.value.get<DrmMetricValue::Tag::int64Value>();
+ break;
+ case DrmMetricValue::Tag::doubleValue:
+ valueHidl.type = DrmMetricGroupHidl::ValueType::DOUBLE_TYPE;
+ valueHidl.doubleValue = value.value.get<DrmMetricValue::Tag::doubleValue>();
+ break;
+ case DrmMetricValue::Tag::stringValue:
+ valueHidl.type = DrmMetricGroupHidl::ValueType::STRING_TYPE;
+ valueHidl.stringValue = value.value.get<DrmMetricValue::Tag::stringValue>();
+ break;
+ default:
+ break;
+ }
+
+ vTmp.push_back(valueHidl);
+ }
+
+ me.values = toHidlVec<ValueHidl>(vTmp);
+ tmpMetric.push_back(me);
+ }
+
+ re.metrics = toHidlVec<DrmMetricHidl>(tmpMetric);
+ resultHidl.push_back(re);
+ }
+
+ return toHidlVec<DrmMetricGroupHidl>(resultHidl);
+}
+
+// DrmSessionClient Definition
+
+struct DrmHalAidl::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
+ explicit DrmSessionClient(DrmHalAidl* drm, const Vector<uint8_t>& sessionId)
+ : mSessionId(sessionId), mDrm(drm) {}
+
+ ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
+
+ const Vector<uint8_t> mSessionId;
+
+ virtual ~DrmSessionClient();
+
+ private:
+ wp<DrmHalAidl> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
+::ndk::ScopedAStatus DrmHalAidl::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+ auto sessionId = mSessionId;
+ sp<DrmHalAidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ status_t err = drm->closeSession(sessionId);
+ if (err != OK) {
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ drm->onEvent(EventTypeAidl::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>());
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmHalAidl::DrmSessionClient::getName(::std::string* _aidl_return) {
+ String8 name;
+ sp<DrmHalAidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ name.append("<deleted>");
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+ name.append("<Get vendor failed or is empty>");
+ }
+ name.append("[");
+ for (size_t i = 0; i < mSessionId.size(); ++i) {
+ name.appendFormat("%02x", mSessionId[i]);
+ }
+ name.append("]");
+ *_aidl_return = name;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+DrmHalAidl::DrmSessionClient::~DrmSessionClient() {
+ DrmSessionManager::Instance()->removeSession(mSessionId);
+}
+
+// DrmHalAidl methods
+DrmHalAidl::DrmHalAidl()
+ : mFactories(makeDrmFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
+
+status_t DrmHalAidl::initCheck() const {
+ return mInitCheck;
+}
+
+DrmHalAidl::~DrmHalAidl() {}
+
+std::vector<std::shared_ptr<IDrmFactoryAidl>> DrmHalAidl::makeDrmFactories() {
+ std::vector<std::shared_ptr<IDrmFactoryAidl>> factories;
+ AServiceManager_forEachDeclaredInstance(
+ IDrmFactoryAidl::descriptor, static_cast<void*>(&factories),
+ [](const char* instance, void* context) {
+ auto fullName = std::string(IDrmFactoryAidl::descriptor) + "/" + std::string(instance);
+ auto factory = IDrmFactoryAidl::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_getService(fullName.c_str())));
+ if (factory == nullptr) {
+ ALOGE("not found IDrmFactory. Instance name:[%s]", fullName.c_str());
+ return;
+ }
+
+ ALOGI("found IDrmFactory. Instance name:[%s]", fullName.c_str());
+ static_cast<std::vector<std::shared_ptr<IDrmFactoryAidl>>*>(context)->emplace_back(
+ factory);
+ });
+
+ return factories;
+}
+
+status_t DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
+ Mutex::Autolock lock(mEventLock);
+ mListener = listener;
+ return NO_ERROR;
+}
+
+status_t DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
+ Mutex::Autolock autoLock(mLock);
+ *isSupported = false;
+ Uuid uuidAidl = toAidlUuid(uuid);
+ SecurityLevel levelAidl = static_cast<SecurityLevel>((int32_t)level);
+ std::string mimeTypeStr = mimeType.string();
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ if (mFactories[i]
+ ->isCryptoSchemeSupported(uuidAidl, mimeTypeStr, levelAidl, isSupported)
+ .isOk()) {
+ if (*isSupported) break;
+ }
+ }
+
+ return OK;
+}
+
+status_t DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ Mutex::Autolock autoLock(mLock);
+
+ Uuid uuidAidl = toAidlUuid(uuid);
+ std::string appPackageNameAidl = toStdString(appPackageName);
+ std::shared_ptr<IDrmPluginAidl> pluginAidl;
+ mMetrics.SetAppPackageName(appPackageName);
+ mMetrics.SetAppUid(AIBinder_getCallingUid());
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ ::ndk::ScopedAStatus status =
+ mFactories[i]->createPlugin(uuidAidl, appPackageNameAidl, &pluginAidl);
+ if (status.isOk()) {
+ if (pluginAidl != NULL) {
+ mPlugin = pluginAidl;
+ break;
+ }
+ } else {
+ DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d",
+ status.getServiceSpecificError());
+ }
+ }
+
+ if (mPlugin == NULL) {
+ DrmUtils::LOG2BE(uuid, "No supported hal instance found");
+ mInitCheck = ERROR_UNSUPPORTED;
+ } else {
+ mInitCheck = OK;
+
+ if (!mPlugin->setListener(shared_from_this()).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+
+ if (mInitCheck != OK) {
+ mPlugin.reset();
+ }
+ }
+
+ return mInitCheck;
+}
+
+status_t DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ SecurityLevel aSecurityLevel = toAidlSecurityLevel(level);
+
+ if (aSecurityLevel == SecurityLevel::UNKNOWN) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+ bool retry = true;
+ do {
+ std::vector<uint8_t> aSessionId;
+
+ ::ndk::ScopedAStatus status = mPlugin->openSession(aSecurityLevel, &aSessionId);
+ if (status.isOk()) sessionId = toVector(aSessionId);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+
+ if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
+ mLock.unlock();
+ // reclaimSession may call back to closeSession, since mLock is
+ // shared between Drm instances, we should unlock here to avoid
+ // deadlock.
+ retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
+ mLock.lock();
+ } else {
+ retry = false;
+ }
+ } while (retry);
+
+ if (err == OK) {
+ std::shared_ptr<DrmSessionClient> client =
+ ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
+ DrmSessionManager::Instance()->addSession(
+ AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
+ sessionId);
+ mOpenSessions.push_back(client);
+ mMetrics.SetSessionStart(sessionId);
+ }
+
+ mMetrics.mOpenSessionCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
+ ::ndk::ScopedAStatus status = mPlugin->closeSession(sessionIdAidl);
+ if (status.isOk()) {
+ DrmSessionManager::Instance()->removeSession(sessionId);
+ for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+ if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+ mOpenSessions.erase(i);
+ break;
+ }
+ }
+
+ status_t response = toStatusTAidl(status.getServiceSpecificError());
+ mMetrics.SetSessionEnd(sessionId);
+ mMetrics.mCloseSessionCounter.Increment(response);
+ return response;
+ }
+ mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
+ return DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ KeyType aKeyType;
+ if (keyType == DrmPlugin::kKeyType_Streaming) {
+ aKeyType = KeyType::STREAMING;
+ } else if (keyType == DrmPlugin::kKeyType_Offline) {
+ aKeyType = KeyType::OFFLINE;
+ } else if (keyType == DrmPlugin::kKeyType_Release) {
+ aKeyType = KeyType::RELEASE;
+ } else {
+ keyRequestTimer.SetAttribute(BAD_VALUE);
+ return BAD_VALUE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
+ std::vector<uint8_t> initDataAidl = toStdVec(initData);
+ KeyRequest keyRequest;
+
+ ::ndk::ScopedAStatus status =
+ mPlugin->getKeyRequest(sessionIdAidl, initDataAidl, toStdString(mimeType), aKeyType,
+ toKeyValueVector(optionalParameters), &keyRequest);
+ if (status.isOk()) {
+ request = toVector(keyRequest.request);
+ defaultUrl = toString8(keyRequest.defaultUrl);
+ *keyRequestType = toKeyRequestType(keyRequest.requestType);
+ }
+
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ keyRequestTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
+ std::vector<uint8_t> responseAidl = toStdVec(response);
+ KeySetId keySetIdsAidl;
+ ::ndk::ScopedAStatus status =
+ mPlugin->provideKeyResponse(sessionIdAidl, responseAidl, &keySetIdsAidl);
+
+ if (status.isOk()) keySetId = toVector(keySetIdsAidl.keySetId);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ keyResponseTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->removeKeys(toStdVec(keySetId));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ KeySetId keySetIdsAidl;
+ keySetIdsAidl.keySetId = toStdVec(keySetId);
+ ::ndk::ScopedAStatus status = mPlugin->restoreKeys(toStdVec(sessionId), keySetIdsAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<KeyValue> infoMapAidl;
+ ::ndk::ScopedAStatus status = mPlugin->queryKeyStatus(toStdVec(sessionId), &infoMapAidl);
+
+ infoMap = toKeyedVector(infoMapAidl);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ ProvisionRequest requestAidl;
+ ::ndk::ScopedAStatus status = mPlugin->getProvisionRequest(
+ toStdString(certType), toStdString(certAuthority), &requestAidl);
+
+ request = toVector(requestAidl.request);
+ defaultUrl = toString8(requestAidl.defaultUrl);
+
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ mMetrics.mGetProvisionRequestCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+ ProvideProvisionResponseResult result;
+ ::ndk::ScopedAStatus status = mPlugin->provideProvisionResponse(toStdVec(response), &result);
+
+ certificate = toVector(result.certificate);
+ wrappedKey = toVector(result.wrappedKey);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<SecureStop> result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecureStops(&result);
+
+ secureStops = toSecureStops(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<SecureStopId> result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecureStopIds(&result);
+
+ secureStopIds = toSecureStopIds(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ SecureStopId ssidAidl;
+ ssidAidl.secureStopId = toStdVec(ssid);
+
+ SecureStop result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecureStop(ssidAidl, &result);
+
+ secureStop = toVector(result.opaqueData);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ OpaqueData ssId;
+ ssId.opaqueData = toStdVec(ssRelease);
+ ::ndk::ScopedAStatus status = mPlugin->releaseSecureStops(ssId);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+ Mutex::Autolock autoLock(mLock);
+
+ INIT_CHECK();
+
+ SecureStopId ssidAidl;
+ ssidAidl.secureStopId = toStdVec(ssid);
+ ::ndk::ScopedAStatus status = mPlugin->removeSecureStop(ssidAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::removeAllSecureStops() {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->releaseAllSecureStops();
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (connected == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+
+ *connected = DrmPlugin::kHdcpLevelUnknown;
+ *max = DrmPlugin::kHdcpLevelUnknown;
+
+ HdcpLevels lvlsAidl;
+ ::ndk::ScopedAStatus status = mPlugin->getHdcpLevels(&lvlsAidl);
+
+ *connected = toHdcpLevel(lvlsAidl.connectedLevel);
+ *max = toHdcpLevel(lvlsAidl.maxLevel);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (open == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+
+ *open = 0;
+ *max = 0;
+
+ NumberOfSessions result;
+ ::ndk::ScopedAStatus status = mPlugin->getNumberOfSessions(&result);
+
+ *open = result.currentSessions;
+ *max = result.maxSessions;
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (level == NULL) {
+ return BAD_VALUE;
+ }
+
+ *level = DrmPlugin::kSecurityLevelUnknown;
+
+ SecurityLevel result;
+ ::ndk::ScopedAStatus status = mPlugin->getSecurityLevel(toStdVec(sessionId), &result);
+
+ *level = toSecurityLevel(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::vector<KeySetId> result;
+ ::ndk::ScopedAStatus status = mPlugin->getOfflineLicenseKeySetIds(&result);
+
+ keySetIds = toKeySetIds(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ KeySetId keySetIdAidl;
+ keySetIdAidl.keySetId = toStdVec(keySetId);
+ ::ndk::ScopedAStatus status = mPlugin->removeOfflineLicense(keySetIdAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
+ Mutex::Autolock autoLock(mLock);
+
+ INIT_CHECK();
+ *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
+
+ KeySetId keySetIdAidl;
+ keySetIdAidl.keySetId = toStdVec(keySetId);
+
+ OfflineLicenseState result;
+ ::ndk::ScopedAStatus status = mPlugin->getOfflineLicenseState(keySetIdAidl, &result);
+
+ *licenseState = toOfflineLicenseState(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyStringInternal(name, value);
+}
+
+status_t DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ std::string result;
+ ::ndk::ScopedAStatus status = mPlugin->getPropertyString(toStdString(name), &result);
+
+ value = toString8(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyByteArrayInternal(name, value);
+}
+
+status_t DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status = mPlugin->getPropertyByteArray(toStdString(name), &result);
+
+ value = toVector(result);
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+ if (name == kPropertyDeviceUniqueId) {
+ mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ }
+ return err;
+}
+
+status_t DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->setPropertyString(toStdString(name), toStdString(value));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ ::ndk::ScopedAStatus status = mPlugin->setPropertyByteArray(toStdString(name), toStdVec(value));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ if (consumer == nullptr) {
+ return UNEXPECTED_NULL;
+ }
+ consumer->consumeFrameworkMetrics(mMetrics);
+
+ // Append vendor metrics if they are supported.
+
+ String8 vendor;
+ String8 description;
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+ ALOGE("Get vendor failed or is empty");
+ vendor = "NONE";
+ }
+ if (getPropertyStringInternal(String8("description"), description) != OK ||
+ description.isEmpty()) {
+ ALOGE("Get description failed or is empty.");
+ description = "NONE";
+ }
+ vendor += ".";
+ vendor += description;
+
+ hidl_vec<DrmMetricGroupHidl> pluginMetrics;
+ status_t err = UNKNOWN_ERROR;
+
+ std::vector<DrmMetricGroupAidl> result;
+ ::ndk::ScopedAStatus status = mPlugin->getMetrics(&result);
+
+ if (status.isOk()) {
+ pluginMetrics = toDrmMetricGroupHidl(result);
+ consumer->consumeHidlMetrics(vendor, pluginMetrics);
+ }
+
+ err = status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+
+ return err;
+}
+
+status_t DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::ndk::ScopedAStatus status =
+ mPlugin->setCipherAlgorithm(toStdVec(sessionId), toStdString(algorithm));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::ndk::ScopedAStatus status =
+ mPlugin->setMacAlgorithm(toStdVec(sessionId), toStdString(algorithm));
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status = mPlugin->encrypt(toStdVec(sessionId), toStdVec(keyId),
+ toStdVec(input), toStdVec(iv), &result);
+
+ output = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status = mPlugin->decrypt(toStdVec(sessionId), toStdVec(keyId),
+ toStdVec(input), toStdVec(iv), &result);
+
+ output = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status =
+ mPlugin->sign(toStdVec(sessionId), toStdVec(keyId), toStdVec(message), &result);
+
+ signature = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::ndk::ScopedAStatus status = mPlugin->verify(toStdVec(sessionId), toStdVec(keyId),
+ toStdVec(message), toStdVec(signature), &match);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ std::vector<uint8_t> result;
+ ::ndk::ScopedAStatus status =
+ mPlugin->signRSA(toStdVec(sessionId), toStdString(algorithm), toStdVec(message),
+ toStdVec(wrappedKey), &result);
+
+ signature = toVector(result);
+
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ std::string mimeAidl(mime);
+ ::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoderDefault(mimeAidl, required);
+ if (!status.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
+ return DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t DrmHalAidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ auto aLevel = toAidlSecurityLevel(securityLevel);
+ std::string mimeAidl(mime);
+ ::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoder(mimeAidl, aLevel, required);
+ if (!status.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
+ return DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ std::string playbackIdAidl(playbackId);
+ ::ndk::ScopedAStatus status = mPlugin->setPlaybackId(toStdVec(sessionId), playbackIdAidl);
+ return status.isOk() ? toStatusTAidl(status.getServiceSpecificError()) : DEAD_OBJECT;
+}
+
+status_t DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs);
+}
+
+void DrmHalAidl::closeOpenSessions() {
+ Mutex::Autolock autoLock(mLock);
+ auto openSessions = mOpenSessions;
+ for (size_t i = 0; i < openSessions.size(); i++) {
+ mLock.unlock();
+ closeSession(openSessions[i]->mSessionId);
+ mLock.lock();
+ }
+ mOpenSessions.clear();
+}
+
+std::string DrmHalAidl::reportPluginMetrics() const {
+ Vector<uint8_t> metricsVector;
+ String8 vendor;
+ String8 description;
+ std::string metricsString;
+ if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
+ getPropertyStringInternal(String8("description"), description) == OK &&
+ getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
+ metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
+ status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
+ mMetrics.GetAppUid());
+ if (res != OK) {
+ ALOGE("Metrics were retrieved but could not be reported: %d", res);
+ }
+ }
+ return metricsString;
+}
+
+std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
+ mediametrics_handle_t item(mediametrics_create("mediadrm"));
+ mediametrics_setUid(item, mMetrics.GetAppUid());
+ String8 vendor;
+ String8 description;
+ status_t result = getPropertyStringInternal(String8("vendor"), vendor);
+ if (result != OK) {
+ ALOGE("Failed to get vendor from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "vendor", vendor.c_str());
+ }
+ result = getPropertyStringInternal(String8("description"), description);
+ if (result != OK) {
+ ALOGE("Failed to get description from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "description", description.c_str());
+ }
+
+ std::string serializedMetrics;
+ result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ if (result != OK) {
+ ALOGE("Failed to serialize framework metrics: %d", result);
+ }
+ std::string b64EncodedMetrics =
+ toBase64StringNoPad(serializedMetrics.data(), serializedMetrics.size());
+ if (!b64EncodedMetrics.empty()) {
+ mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
+ }
+ if (!pluginMetrics.empty()) {
+ mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str());
+ }
+ if (!mediametrics_selfRecord(item)) {
+ ALOGE("Failed to self record framework metrics");
+ }
+ mediametrics_delete(item);
+ return serializedMetrics;
+}
+
+void DrmHalAidl::cleanup() {
+ closeOpenSessions();
+
+ Mutex::Autolock autoLock(mLock);
+ reportFrameworkMetrics(reportPluginMetrics());
+
+ setListener(NULL);
+ mInitCheck = NO_INIT;
+ if (mPlugin != NULL) {
+ if (!mPlugin->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ }
+
+ mPlugin.reset();
+}
+
+status_t DrmHalAidl::destroyPlugin() {
+ cleanup();
+ return OK;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onEvent(EventTypeAidl eventTypeAidl,
+ const std::vector<uint8_t>& sessionId,
+ const std::vector<uint8_t>& data) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mMetrics.mEventCounter.Increment((uint32_t)eventTypeAidl);
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ DrmPlugin::EventType eventType;
+ switch (eventTypeAidl) {
+ case EventTypeAidl::PROVISION_REQUIRED:
+ eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
+ break;
+ case EventTypeAidl::KEY_NEEDED:
+ eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
+ break;
+ case EventTypeAidl::KEY_EXPIRED:
+ eventType = DrmPlugin::kDrmPluginEventKeyExpired;
+ break;
+ case EventTypeAidl::VENDOR_DEFINED:
+ eventType = DrmPlugin::kDrmPluginEventVendorDefined;
+ break;
+ case EventTypeAidl::SESSION_RECLAIMED:
+ eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
+ break;
+ default:
+ return _aidl_status;
+ }
+
+ listener->sendEvent(eventType, toHidlVec(toVector(sessionId)), toHidlVec(toVector(data)));
+ }
+
+ return _aidl_status;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onExpirationUpdate(const std::vector<uint8_t>& sessionId,
+ int64_t expiryTimeInMS) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendExpirationUpdate(toHidlVec(toVector(sessionId)), expiryTimeInMS);
+ }
+
+ return _aidl_status;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onKeysChange(const std::vector<uint8_t>& sessionId,
+ const std::vector<KeyStatus>& keyStatusListAidl,
+ bool hasNewUsableKey) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ std::vector<DrmKeyStatus> keyStatusList;
+ size_t nKeys = keyStatusListAidl.size();
+ for (size_t i = 0; i < nKeys; ++i) {
+ const KeyStatus& keyStatus = keyStatusListAidl[i];
+ uint32_t type;
+ switch (keyStatus.type) {
+ case KeyStatusType::USABLE:
+ type = DrmPlugin::kKeyStatusType_Usable;
+ break;
+ case KeyStatusType::EXPIRED:
+ type = DrmPlugin::kKeyStatusType_Expired;
+ break;
+ case KeyStatusType::OUTPUTNOTALLOWED:
+ type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
+ break;
+ case KeyStatusType::STATUSPENDING:
+ type = DrmPlugin::kKeyStatusType_StatusPending;
+ break;
+ case KeyStatusType::USABLEINFUTURE:
+ type = DrmPlugin::kKeyStatusType_UsableInFuture;
+ break;
+ case KeyStatusType::INTERNALERROR:
+ default:
+ type = DrmPlugin::kKeyStatusType_InternalError;
+ break;
+ }
+ keyStatusList.push_back({type, toHidlVec(toVector(keyStatus.keyId))});
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)keyStatus.type);
+ }
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendKeysChange(toHidlVec(toVector(sessionId)), keyStatusList, hasNewUsableKey);
+ }
+ else {
+ // There's no listener. But we still want to count the key change
+ // events.
+ size_t nKeys = keyStatusListAidl.size();
+
+ for (size_t i = 0; i < nKeys; i++) {
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)keyStatusListAidl[i].type);
+ }
+ }
+
+ return _aidl_status;
+}
+
+::ndk::ScopedAStatus DrmHalAidl::onSessionLostState(const std::vector<uint8_t>& sessionId) {
+ ::ndk::ScopedAStatus _aidl_status;
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendSessionLostState(toHidlVec(toVector(sessionId)));
+ }
+
+ return _aidl_status;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
new file mode 100644
index 0000000..a5dd4d7
--- /dev/null
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -0,0 +1,1516 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "DrmHalHidl"
+
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <android/binder_manager.h>
+#include <android/hardware/drm/1.2/types.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <media/EventMetric.h>
+#include <media/MediaMetrics.h>
+#include <media/PluginMetricsReporting.h>
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <mediadrm/DrmHalHidl.h>
+#include <mediadrm/DrmSessionClientInterface.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmUtils.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/Log.h>
+
+#include <iomanip>
+#include <vector>
+
+using ::android::sp;
+using ::android::DrmUtils::toStatusT;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+using ::android::os::PersistableBundle;
+using drm::V1_0::KeyedVector;
+using drm::V1_0::KeyRequestType;
+using drm::V1_0::KeyType;
+using drm::V1_0::KeyValue;
+using drm::V1_0::SecureStop;
+using drm::V1_0::SecureStopId;
+using drm::V1_0::Status;
+using drm::V1_1::HdcpLevel;
+using drm::V1_1::SecureStopRelease;
+using drm::V1_1::SecurityLevel;
+using drm::V1_2::KeySetId;
+using drm::V1_2::KeyStatusType;
+
+typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
+typedef drm::V1_2::Status Status_V1_2;
+typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
+
+namespace {
+
+// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
+// in the MediaDrm API.
+constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
+constexpr char kEqualsSign[] = "=";
+
+template <typename T>
+std::string toBase64StringNoPad(const T* data, size_t size) {
+ // Note that the base 64 conversion only works with arrays of single-byte
+ // values. If the source is empty or is not an array of single-byte values,
+ // return empty string.
+ if (size == 0 || sizeof(data[0]) != 1) {
+ return "";
+ }
+
+ android::AString outputString;
+ encodeBase64(data, size, &outputString);
+ // Remove trailing equals padding if it exists.
+ while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
+ outputString.erase(outputString.size() - 1, 1);
+ }
+
+ return std::string(outputString.c_str(), outputString.size());
+}
+
+} // anonymous namespace
+
+namespace android {
+
+#define INIT_CHECK() \
+ { \
+ if (mInitCheck != OK) return mInitCheck; \
+ }
+
+static const Vector<uint8_t> toVector(const hidl_vec<uint8_t>& vec) {
+ Vector<uint8_t> vector;
+ vector.appendArray(vec.data(), vec.size());
+ return *const_cast<const Vector<uint8_t>*>(&vector);
+}
+
+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 String8 toString8(const hidl_string& string) {
+ return String8(string.c_str());
+}
+
+static hidl_string toHidlString(const String8& string) {
+ return hidl_string(string.string());
+}
+
+static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
+ switch (level) {
+ case SecurityLevel::SW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelSwSecureCrypto;
+ case SecurityLevel::SW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelSwSecureDecode;
+ case SecurityLevel::HW_SECURE_CRYPTO:
+ return DrmPlugin::kSecurityLevelHwSecureCrypto;
+ case SecurityLevel::HW_SECURE_DECODE:
+ return DrmPlugin::kSecurityLevelHwSecureDecode;
+ case SecurityLevel::HW_SECURE_ALL:
+ return DrmPlugin::kSecurityLevelHwSecureAll;
+ default:
+ return DrmPlugin::kSecurityLevelUnknown;
+ }
+}
+
+static SecurityLevel toHidlSecurityLevel(DrmPlugin::SecurityLevel level) {
+ switch (level) {
+ case DrmPlugin::kSecurityLevelSwSecureCrypto:
+ return SecurityLevel::SW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelSwSecureDecode:
+ return SecurityLevel::SW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureCrypto:
+ return SecurityLevel::HW_SECURE_CRYPTO;
+ case DrmPlugin::kSecurityLevelHwSecureDecode:
+ return SecurityLevel::HW_SECURE_DECODE;
+ case DrmPlugin::kSecurityLevelHwSecureAll:
+ return SecurityLevel::HW_SECURE_ALL;
+ default:
+ return SecurityLevel::UNKNOWN;
+ }
+}
+
+static DrmPlugin::OfflineLicenseState toOfflineLicenseState(OfflineLicenseState licenseState) {
+ switch (licenseState) {
+ case OfflineLicenseState::USABLE:
+ return DrmPlugin::kOfflineLicenseStateUsable;
+ case OfflineLicenseState::INACTIVE:
+ return DrmPlugin::kOfflineLicenseStateReleased;
+ default:
+ return DrmPlugin::kOfflineLicenseStateUnknown;
+ }
+}
+
+static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel_V1_2 level) {
+ switch (level) {
+ case HdcpLevel_V1_2::HDCP_NONE:
+ return DrmPlugin::kHdcpNone;
+ case HdcpLevel_V1_2::HDCP_V1:
+ return DrmPlugin::kHdcpV1;
+ case HdcpLevel_V1_2::HDCP_V2:
+ return DrmPlugin::kHdcpV2;
+ case HdcpLevel_V1_2::HDCP_V2_1:
+ return DrmPlugin::kHdcpV2_1;
+ case HdcpLevel_V1_2::HDCP_V2_2:
+ return DrmPlugin::kHdcpV2_2;
+ case HdcpLevel_V1_2::HDCP_V2_3:
+ return DrmPlugin::kHdcpV2_3;
+ case HdcpLevel_V1_2::HDCP_NO_OUTPUT:
+ return DrmPlugin::kHdcpNoOutput;
+ default:
+ return DrmPlugin::kHdcpLevelUnknown;
+ }
+}
+static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>& keyedVector) {
+ std::vector<KeyValue> stdKeyedVector;
+ for (size_t i = 0; i < keyedVector.size(); i++) {
+ KeyValue keyValue;
+ keyValue.key = toHidlString(keyedVector.keyAt(i));
+ keyValue.value = toHidlString(keyedVector.valueAt(i));
+ stdKeyedVector.push_back(keyValue);
+ }
+ return ::KeyedVector(stdKeyedVector);
+}
+
+static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector& hKeyedVector) {
+ KeyedVector<String8, String8> keyedVector;
+ for (size_t i = 0; i < hKeyedVector.size(); i++) {
+ keyedVector.add(toString8(hKeyedVector[i].key), toString8(hKeyedVector[i].value));
+ }
+ return keyedVector;
+}
+
+static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>& hSecureStops) {
+ List<Vector<uint8_t>> secureStops;
+ for (size_t i = 0; i < hSecureStops.size(); i++) {
+ secureStops.push_back(toVector(hSecureStops[i].opaqueData));
+ }
+ return secureStops;
+}
+
+static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>& hSecureStopIds) {
+ List<Vector<uint8_t>> secureStopIds;
+ for (size_t i = 0; i < hSecureStopIds.size(); i++) {
+ secureStopIds.push_back(toVector(hSecureStopIds[i]));
+ }
+ return secureStopIds;
+}
+
+static List<Vector<uint8_t>> toKeySetIds(const hidl_vec<KeySetId>& hKeySetIds) {
+ List<Vector<uint8_t>> keySetIds;
+ for (size_t i = 0; i < hKeySetIds.size(); i++) {
+ keySetIds.push_back(toVector(hKeySetIds[i]));
+ }
+ return keySetIds;
+}
+
+Mutex DrmHalHidl::mLock;
+
+struct DrmHalHidl::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
+ explicit DrmSessionClient(DrmHalHidl* drm, const Vector<uint8_t>& sessionId)
+ : mSessionId(sessionId), mDrm(drm) {}
+
+ ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
+
+ const Vector<uint8_t> mSessionId;
+
+ virtual ~DrmSessionClient();
+
+ private:
+ wp<DrmHalHidl> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
+::ndk::ScopedAStatus DrmHalHidl::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+ auto sessionId = mSessionId;
+ sp<DrmHalHidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ status_t err = drm->closeSession(sessionId);
+ if (err != OK) {
+ *_aidl_return = false;
+ return ::ndk::ScopedAStatus::ok();
+ }
+ drm->sendEvent(EventType::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>());
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus DrmHalHidl::DrmSessionClient::getName(::std::string* _aidl_return) {
+ String8 name;
+ sp<DrmHalHidl> drm = mDrm.promote();
+ if (drm == NULL) {
+ name.append("<deleted>");
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+ name.append("<Get vendor failed or is empty>");
+ }
+ name.append("[");
+ for (size_t i = 0; i < mSessionId.size(); ++i) {
+ name.appendFormat("%02x", mSessionId[i]);
+ }
+ name.append("]");
+ *_aidl_return = name;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+DrmHalHidl::DrmSessionClient::~DrmSessionClient() {
+ DrmSessionManager::Instance()->removeSession(mSessionId);
+}
+
+DrmHalHidl::DrmHalHidl()
+ : mFactories(makeDrmFactories()),
+ mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
+
+void DrmHalHidl::closeOpenSessions() {
+ Mutex::Autolock autoLock(mLock);
+ auto openSessions = mOpenSessions;
+ for (size_t i = 0; i < openSessions.size(); i++) {
+ mLock.unlock();
+ closeSession(openSessions[i]->mSessionId);
+ mLock.lock();
+ }
+ mOpenSessions.clear();
+}
+
+DrmHalHidl::~DrmHalHidl() {}
+
+void DrmHalHidl::cleanup() {
+ closeOpenSessions();
+
+ Mutex::Autolock autoLock(mLock);
+ reportFrameworkMetrics(reportPluginMetrics());
+
+ setListener(NULL);
+ mInitCheck = NO_INIT;
+ if (mPluginV1_2 != NULL) {
+ if (!mPluginV1_2->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ } else if (mPlugin != NULL) {
+ if (!mPlugin->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ }
+ mPlugin.clear();
+ mPluginV1_1.clear();
+ mPluginV1_2.clear();
+ mPluginV1_4.clear();
+}
+
+std::vector<sp<IDrmFactory>> DrmHalHidl::makeDrmFactories() {
+ static std::vector<sp<IDrmFactory>> factories(DrmUtils::MakeDrmFactories());
+ if (factories.size() == 0) {
+ // must be in passthrough mode, load the default passthrough service
+ auto passthrough = IDrmFactory::getService();
+ if (passthrough != NULL) {
+ DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
+ factories.push_back(passthrough);
+ } else {
+ DrmUtils::LOG2BE("Failed to find any drm factories");
+ }
+ }
+ return factories;
+}
+
+sp<IDrmPlugin> DrmHalHidl::makeDrmPlugin(const sp<IDrmFactory>& factory, const uint8_t uuid[16],
+ const String8& appPackageName) {
+ mAppPackageName = appPackageName;
+ mMetrics.SetAppPackageName(appPackageName);
+ mMetrics.SetAppUid(AIBinder_getCallingUid());
+
+ sp<IDrmPlugin> plugin;
+ Return<void> hResult = factory->createPlugin(
+ uuid, appPackageName.string(), [&](Status status, const sp<IDrmPlugin>& hPlugin) {
+ if (status != Status::OK) {
+ DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
+ return;
+ }
+ plugin = hPlugin;
+ });
+
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE(uuid, "createPlugin remote call failed: %s",
+ hResult.description().c_str());
+ }
+
+ return plugin;
+}
+
+status_t DrmHalHidl::initCheck() const {
+ return mInitCheck;
+}
+
+status_t DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
+ Mutex::Autolock lock(mEventLock);
+ mListener = listener;
+ return NO_ERROR;
+}
+
+Return<void> DrmHalHidl::sendEvent(EventType hEventType, const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<uint8_t>& data) {
+ mMetrics.mEventCounter.Increment((uint32_t)hEventType);
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ DrmPlugin::EventType eventType;
+ switch (hEventType) {
+ case EventType::PROVISION_REQUIRED:
+ eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
+ break;
+ case EventType::KEY_NEEDED:
+ eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
+ break;
+ case EventType::KEY_EXPIRED:
+ eventType = DrmPlugin::kDrmPluginEventKeyExpired;
+ break;
+ case EventType::VENDOR_DEFINED:
+ eventType = DrmPlugin::kDrmPluginEventVendorDefined;
+ break;
+ case EventType::SESSION_RECLAIMED:
+ eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
+ break;
+ default:
+ return Void();
+ }
+ listener->sendEvent(eventType, sessionId, data);
+ }
+ return Void();
+}
+
+Return<void> DrmHalHidl::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+ int64_t expiryTimeInMS) {
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+ }
+ return Void();
+}
+
+Return<void> DrmHalHidl::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_0>& keyStatusList_V1_0,
+ bool hasNewUsableKey) {
+ std::vector<KeyStatus> keyStatusVec;
+ for (const auto& keyStatus_V1_0 : keyStatusList_V1_0) {
+ keyStatusVec.push_back(
+ {keyStatus_V1_0.keyId, static_cast<KeyStatusType>(keyStatus_V1_0.type)});
+ }
+ hidl_vec<KeyStatus> keyStatusList_V1_2(keyStatusVec);
+ return sendKeysChange_1_2(sessionId, keyStatusList_V1_2, hasNewUsableKey);
+}
+
+Return<void> DrmHalHidl::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& hKeyStatusList,
+ bool hasNewUsableKey) {
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ std::vector<DrmKeyStatus> keyStatusList;
+ size_t nKeys = hKeyStatusList.size();
+ for (size_t i = 0; i < nKeys; ++i) {
+ const KeyStatus& keyStatus = hKeyStatusList[i];
+ uint32_t type;
+ switch (keyStatus.type) {
+ case KeyStatusType::USABLE:
+ type = DrmPlugin::kKeyStatusType_Usable;
+ break;
+ case KeyStatusType::EXPIRED:
+ type = DrmPlugin::kKeyStatusType_Expired;
+ break;
+ case KeyStatusType::OUTPUTNOTALLOWED:
+ type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
+ break;
+ case KeyStatusType::STATUSPENDING:
+ type = DrmPlugin::kKeyStatusType_StatusPending;
+ break;
+ case KeyStatusType::USABLEINFUTURE:
+ type = DrmPlugin::kKeyStatusType_UsableInFuture;
+ break;
+ case KeyStatusType::INTERNALERROR:
+ default:
+ type = DrmPlugin::kKeyStatusType_InternalError;
+ break;
+ }
+ keyStatusList.push_back({type, keyStatus.keyId});
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)keyStatus.type);
+ }
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+ } else {
+ // There's no listener. But we still want to count the key change
+ // events.
+ size_t nKeys = hKeyStatusList.size();
+ for (size_t i = 0; i < nKeys; i++) {
+ mMetrics.mKeyStatusChangeCounter.Increment((uint32_t)hKeyStatusList[i].type);
+ }
+ }
+
+ return Void();
+}
+
+Return<void> DrmHalHidl::sendSessionLostState(const hidl_vec<uint8_t>& sessionId) {
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock lock(mNotifyLock);
+ listener->sendSessionLostState(sessionId);
+ }
+ return Void();
+}
+
+status_t DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool* isSupported) {
+ *isSupported = false;
+
+ // handle default value cases
+ if (level == DrmPlugin::kSecurityLevelUnknown) {
+ if (mimeType == "") {
+ // isCryptoSchemeSupported(uuid)
+ *isSupported = true;
+ } else {
+ // isCryptoSchemeSupported(uuid, mimeType)
+ *isSupported = factory->isContentTypeSupported(mimeType.string());
+ }
+ return OK;
+ } else if (mimeType == "") {
+ return BAD_VALUE;
+ }
+
+ sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
+ if (factoryV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ } else {
+ *isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
+ toHidlSecurityLevel(level));
+ return OK;
+ }
+}
+
+status_t DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel level, bool* isSupported) {
+ Mutex::Autolock autoLock(mLock);
+ *isSupported = false;
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ return matchMimeTypeAndSecurityLevel(mFactories[i], uuid, mimeType, level, isSupported);
+ }
+ }
+ return OK;
+}
+
+status_t DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+ Mutex::Autolock autoLock(mLock);
+
+ for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
+ auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
+ if (hResult.isOk() && hResult) {
+ auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+ if (plugin != NULL) {
+ mPlugin = plugin;
+ mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
+ mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
+ mPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mPlugin);
+ break;
+ }
+ }
+ }
+
+ if (mPlugin == NULL) {
+ DrmUtils::LOG2BE(uuid, "No supported hal instance found");
+ mInitCheck = ERROR_UNSUPPORTED;
+ } else {
+ mInitCheck = OK;
+ if (mPluginV1_2 != NULL) {
+ if (!mPluginV1_2->setListener(this).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ } else if (!mPlugin->setListener(this).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ if (mInitCheck != OK) {
+ mPlugin.clear();
+ mPluginV1_1.clear();
+ mPluginV1_2.clear();
+ mPluginV1_4.clear();
+ }
+ }
+
+ return mInitCheck;
+}
+
+status_t DrmHalHidl::destroyPlugin() {
+ cleanup();
+ return OK;
+}
+
+status_t DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ SecurityLevel hSecurityLevel = toHidlSecurityLevel(level);
+ bool setSecurityLevel = true;
+
+ if (level == DrmPlugin::kSecurityLevelMax) {
+ setSecurityLevel = false;
+ } else {
+ if (hSecurityLevel == SecurityLevel::UNKNOWN) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+ }
+
+ status_t err = UNKNOWN_ERROR;
+ bool retry = true;
+ do {
+ hidl_vec<uint8_t> hSessionId;
+
+ Return<void> hResult;
+ if (mPluginV1_1 == NULL || !setSecurityLevel) {
+ hResult = mPlugin->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
+ if (status == Status::OK) {
+ sessionId = toVector(id);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
+ [&](Status status, const hidl_vec<uint8_t>& id) {
+ if (status == Status::OK) {
+ sessionId = toVector(id);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ if (!hResult.isOk()) {
+ err = DEAD_OBJECT;
+ }
+
+ if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
+ mLock.unlock();
+ // reclaimSession may call back to closeSession, since mLock is
+ // shared between Drm instances, we should unlock here to avoid
+ // deadlock.
+ retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
+ mLock.lock();
+ } else {
+ retry = false;
+ }
+ } while (retry);
+
+ if (err == OK) {
+ std::shared_ptr<DrmSessionClient> client =
+ ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
+ DrmSessionManager::Instance()->addSession(
+ AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
+ sessionId);
+ mOpenSessions.push_back(client);
+ mMetrics.SetSessionStart(sessionId);
+ }
+
+ mMetrics.mOpenSessionCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
+ if (status.isOk()) {
+ if (status == Status::OK) {
+ DrmSessionManager::Instance()->removeSession(sessionId);
+ for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+ if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+ mOpenSessions.erase(i);
+ break;
+ }
+ }
+ }
+ status_t response = toStatusT(status);
+ mMetrics.SetSessionEnd(sessionId);
+ mMetrics.mCloseSessionCounter.Increment(response);
+ return response;
+ }
+ mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
+ return DEAD_OBJECT;
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType::INITIAL:
+ return DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case KeyRequestType::RENEWAL:
+ return DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case KeyRequestType::RELEASE:
+ return DrmPlugin::kKeyRequestType_Release;
+ break;
+ default:
+ return DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType_1_1(KeyRequestType_V1_1 keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType_V1_1::NONE:
+ return DrmPlugin::kKeyRequestType_None;
+ break;
+ case KeyRequestType_V1_1::UPDATE:
+ return DrmPlugin::kKeyRequestType_Update;
+ break;
+ default:
+ return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType));
+ break;
+ }
+}
+
+status_t DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ KeyType hKeyType;
+ if (keyType == DrmPlugin::kKeyType_Streaming) {
+ hKeyType = KeyType::STREAMING;
+ } else if (keyType == DrmPlugin::kKeyType_Offline) {
+ hKeyType = KeyType::OFFLINE;
+ } else if (keyType == DrmPlugin::kKeyType_Release) {
+ hKeyType = KeyType::RELEASE;
+ } else {
+ keyRequestTimer.SetAttribute(BAD_VALUE);
+ return BAD_VALUE;
+ }
+
+ ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
+
+ status_t err = UNKNOWN_ERROR;
+ Return<void> hResult;
+
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getKeyRequest_1_2(
+ toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType,
+ hOptionalParameters,
+ [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) {
+ if (status == Status_V1_2::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ } else if (mPluginV1_1 != NULL) {
+ hResult = mPluginV1_1->getKeyRequest_1_1(
+ toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType,
+ hOptionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPlugin->getKeyRequest(
+ toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType,
+ hOptionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ keyRequestTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response,
+ Vector<uint8_t>& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+ EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response),
+ [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
+ if (status == Status::OK) {
+ keySetId = toVector(hKeySetId);
+ }
+ err = toStatusT(status);
+ });
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ keyResponseTimer.SetAttribute(err);
+ return err;
+}
+
+status_t DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId), toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ ::KeyedVector hInfoMap;
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->queryKeyStatus(
+ toHidlVec(sessionId), [&](Status status, const hidl_vec<KeyValue>& map) {
+ if (status == Status::OK) {
+ infoMap = toKeyedVector(map);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+ Return<void> hResult;
+
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getProvisionRequest_1_2(
+ toHidlString(certType), toHidlString(certAuthority),
+ [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status_V1_2::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ hResult = mPlugin->getProvisionRequest(toHidlString(certType), toHidlString(certAuthority),
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ }
+ err = toStatusT(status);
+ });
+ }
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ mMetrics.mGetProvisionRequestCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->provideProvisionResponse(
+ toHidlVec(response), [&](Status status, const hidl_vec<uint8_t>& hCertificate,
+ const hidl_vec<uint8_t>& hWrappedKey) {
+ if (status == Status::OK) {
+ certificate = toVector(hCertificate);
+ wrappedKey = toVector(hWrappedKey);
+ }
+ err = toStatusT(status);
+ });
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ mMetrics.mProvideProvisionResponseCounter.Increment(err);
+ return err;
+}
+
+status_t DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->getSecureStops([&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
+ if (status == Status::OK) {
+ secureStops = toSecureStops(hSecureStops);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_1->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
+ if (status == Status::OK) {
+ secureStopIds = toSecureStopIds(hSecureStopIds);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->getSecureStop(
+ toHidlVec(ssid), [&](Status status, const SecureStop& hSecureStop) {
+ if (status == Status::OK) {
+ secureStop = toVector(hSecureStop.opaqueData);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status(Status::ERROR_DRM_UNKNOWN);
+ if (mPluginV1_1 != NULL) {
+ SecureStopRelease secureStopRelease;
+ secureStopRelease.opaqueData = toHidlVec(ssRelease);
+ status = mPluginV1_1->releaseSecureStops(secureStopRelease);
+ } else {
+ status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
+ }
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::removeAllSecureStops() {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status(Status::ERROR_DRM_UNKNOWN);
+ if (mPluginV1_1 != NULL) {
+ status = mPluginV1_1->removeAllSecureStops();
+ } else {
+ status = mPlugin->releaseAllSecureStops();
+ }
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+ DrmPlugin::HdcpLevel* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (connected == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ *connected = DrmPlugin::kHdcpLevelUnknown;
+ *max = DrmPlugin::kHdcpLevelUnknown;
+
+ Return<void> hResult;
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getHdcpLevels_1_2([&](Status_V1_2 status,
+ const HdcpLevel_V1_2& hConnected,
+ const HdcpLevel_V1_2& hMax) {
+ if (status == Status_V1_2::OK) {
+ *connected = toHdcpLevel(hConnected);
+ *max = toHdcpLevel(hMax);
+ }
+ err = toStatusT(status);
+ });
+ } else if (mPluginV1_1 != NULL) {
+ hResult = mPluginV1_1->getHdcpLevels(
+ [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
+ if (status == Status::OK) {
+ *connected = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hConnected));
+ *max = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hMax));
+ }
+ err = toStatusT(status);
+ });
+ } else {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (open == NULL || max == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ *open = 0;
+ *max = 0;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ Return<void> hResult =
+ mPluginV1_1->getNumberOfSessions([&](Status status, uint32_t hOpen, uint32_t hMax) {
+ if (status == Status::OK) {
+ *open = hOpen;
+ *max = hMax;
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ if (level == NULL) {
+ return BAD_VALUE;
+ }
+ status_t err = UNKNOWN_ERROR;
+
+ if (mPluginV1_1 == NULL) {
+ return ERROR_DRM_CANNOT_HANDLE;
+ }
+
+ *level = DrmPlugin::kSecurityLevelUnknown;
+
+ Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
+ [&](Status status, SecurityLevel hLevel) {
+ if (status == Status::OK) {
+ *level = toSecurityLevel(hLevel);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
+ [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
+ if (status == Status::OK) {
+ keySetIds = toKeySetIds(hKeySetIds);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPluginV1_2 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+ *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPluginV1_2->getOfflineLicenseState(
+ toHidlVec(keySetId), [&](Status status, OfflineLicenseState hLicenseState) {
+ if (status == Status::OK) {
+ *licenseState = toOfflineLicenseState(hLicenseState);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyStringInternal(name, value);
+}
+
+status_t DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->getPropertyString(
+ toHidlString(name), [&](Status status, const hidl_string& hValue) {
+ if (status == Status::OK) {
+ value = toString8(hValue);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+ Mutex::Autolock autoLock(mLock);
+ return getPropertyByteArrayInternal(name, value);
+}
+
+status_t DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
+ Vector<uint8_t>& value) const {
+ // This function is internal to the class and should only be called while
+ // mLock is already held.
+ INIT_CHECK();
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->getPropertyByteArray(
+ toHidlString(name), [&](Status status, const hidl_vec<uint8_t>& hValue) {
+ if (status == Status::OK) {
+ value = toVector(hValue);
+ }
+ err = toStatusT(status);
+ });
+
+ err = hResult.isOk() ? err : DEAD_OBJECT;
+ if (name == kPropertyDeviceUniqueId) {
+ mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+ }
+ return err;
+}
+
+status_t DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->setPropertyString(toHidlString(name), toHidlString(value));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name), toHidlVec(value));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+ if (consumer == nullptr) {
+ return UNEXPECTED_NULL;
+ }
+ consumer->consumeFrameworkMetrics(mMetrics);
+
+ // Append vendor metrics if they are supported.
+ if (mPluginV1_1 != NULL) {
+ String8 vendor;
+ String8 description;
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+ ALOGE("Get vendor failed or is empty");
+ vendor = "NONE";
+ }
+ if (getPropertyStringInternal(String8("description"), description) != OK ||
+ description.isEmpty()) {
+ ALOGE("Get description failed or is empty.");
+ description = "NONE";
+ }
+ vendor += ".";
+ vendor += description;
+
+ hidl_vec<DrmMetricGroup> pluginMetrics;
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> status =
+ mPluginV1_1->getMetrics([&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
+ if (status != Status::OK) {
+ ALOGV("Error getting plugin metrics: %d", status);
+ } else {
+ consumer->consumeHidlMetrics(vendor, pluginMetrics);
+ }
+ err = toStatusT(status);
+ });
+ return status.isOk() ? err : DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+ String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Return<Status> status =
+ mPlugin->setCipherAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
+ return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->encrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
+ toHidlVec(iv), [&](Status status, const hidl_vec<uint8_t>& hOutput) {
+ if (status == Status::OK) {
+ output = toVector(hOutput);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->decrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
+ toHidlVec(iv), [&](Status status, const hidl_vec<uint8_t>& hOutput) {
+ if (status == Status::OK) {
+ output = toVector(hOutput);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->sign(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
+ [&](Status status, const hidl_vec<uint8_t>& hSignature) {
+ if (status == Status::OK) {
+ signature = toVector(hSignature);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult =
+ mPlugin->verify(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
+ toHidlVec(signature), [&](Status status, bool hMatch) {
+ if (status == Status::OK) {
+ match = hMatch;
+ } else {
+ match = false;
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature) {
+ Mutex::Autolock autoLock(mLock);
+ INIT_CHECK();
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> hResult = mPlugin->signRSA(
+ toHidlVec(sessionId), toHidlString(algorithm), toHidlVec(message),
+ toHidlVec(wrappedKey), [&](Status status, const hidl_vec<uint8_t>& hSignature) {
+ if (status == Status::OK) {
+ signature = toVector(hSignature);
+ }
+ err = toStatusT(status);
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+std::string DrmHalHidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
+ mediametrics_handle_t item(mediametrics_create("mediadrm"));
+ mediametrics_setUid(item, mMetrics.GetAppUid());
+ String8 vendor;
+ String8 description;
+ status_t result = getPropertyStringInternal(String8("vendor"), vendor);
+ if (result != OK) {
+ ALOGE("Failed to get vendor from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "vendor", vendor.c_str());
+ }
+ result = getPropertyStringInternal(String8("description"), description);
+ if (result != OK) {
+ ALOGE("Failed to get description from drm plugin: %d", result);
+ } else {
+ mediametrics_setCString(item, "description", description.c_str());
+ }
+
+ std::string serializedMetrics;
+ result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+ if (result != OK) {
+ ALOGE("Failed to serialize framework metrics: %d", result);
+ }
+ std::string b64EncodedMetrics =
+ toBase64StringNoPad(serializedMetrics.data(), serializedMetrics.size());
+ if (!b64EncodedMetrics.empty()) {
+ mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
+ }
+ if (!pluginMetrics.empty()) {
+ mediametrics_setCString(item, "plugin_metrics", pluginMetrics.c_str());
+ }
+ if (!mediametrics_selfRecord(item)) {
+ ALOGE("Failed to self record framework metrics");
+ }
+ mediametrics_delete(item);
+ return serializedMetrics;
+}
+
+std::string DrmHalHidl::reportPluginMetrics() const {
+ Vector<uint8_t> metricsVector;
+ String8 vendor;
+ String8 description;
+ std::string metricsString;
+ if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
+ getPropertyStringInternal(String8("description"), description) == OK &&
+ getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
+ metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
+ status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
+ mMetrics.GetAppUid());
+ if (res != OK) {
+ ALOGE("Metrics were retrieved but could not be reported: %d", res);
+ }
+ }
+ return metricsString;
+}
+
+status_t DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ if (mPluginV1_4 == NULL) {
+ return false;
+ }
+ auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (required) {
+ *required = hResult;
+ }
+ return OK;
+}
+
+status_t DrmHalHidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const {
+ Mutex::Autolock autoLock(mLock);
+ if (mPluginV1_4 == NULL) {
+ return false;
+ }
+ auto hLevel = toHidlSecurityLevel(securityLevel);
+ auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
+ if (!hResult.isOk()) {
+ DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (required) {
+ *required = hResult;
+ }
+ return OK;
+}
+
+status_t DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+ Mutex::Autolock autoLock(mLock);
+ if (mPluginV1_4 == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+ auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
+ return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+}
+
+status_t DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+ Mutex::Autolock autoLock(mLock);
+ return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp
index 996fd19..77b5343 100644
--- a/drm/libmediadrm/DrmMetrics.cpp
+++ b/drm/libmediadrm/DrmMetrics.cpp
@@ -123,20 +123,19 @@
});
mKeyStatusChangeCounter.ExportValues(
- [&](const KeyStatusType key_status_type, const int64_t value) {
+ [&](const uint32_t key_status_type, const int64_t value) {
DrmFrameworkMetrics::Counter *counter =
metrics.add_key_status_change_counter();
counter->set_count(value);
- counter->mutable_attributes()->set_key_status_type(
- (uint32_t)key_status_type);
+ counter->mutable_attributes()->set_key_status_type(key_status_type);
});
mEventCounter.ExportValues(
- [&](const EventType event_type, const int64_t value) {
+ [&](const uint32_t event_type, const int64_t value) {
DrmFrameworkMetrics::Counter *counter =
metrics.add_event_callback_counter();
counter->set_count(value);
- counter->mutable_attributes()->set_event_type((uint32_t)event_type);
+ counter->mutable_attributes()->set_event_type(event_type);
});
mGetDeviceUniqueIdCounter.ExportValues(
diff --git a/drm/libmediadrm/DrmMetricsConsumer.cpp b/drm/libmediadrm/DrmMetricsConsumer.cpp
index 5f0b26e..dca3050 100644
--- a/drm/libmediadrm/DrmMetricsConsumer.cpp
+++ b/drm/libmediadrm/DrmMetricsConsumer.cpp
@@ -32,26 +32,24 @@
namespace {
-template <typename T> std::string GetAttributeName(T type);
-
-template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
- static const char *type_names[] = {"USABLE", "EXPIRED",
+std::string GetAttributeName(std::string typeName, uint32_t attribute) {
+ if (typeName == "KeyStatusChange") {
+ static const char *type_names[] = {"USABLE", "EXPIRED",
"OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
"INTERNAL_ERROR", "USABLE_IN_FUTURE"};
- if (((size_t)type) >= arraysize(type_names)) {
- return "UNKNOWN_TYPE";
+ if (attribute >= arraysize(type_names)) {
+ return "UNKNOWN_TYPE";
+ }
+ return type_names[attribute];
}
- return type_names[(size_t)type];
-}
-
-template <> std::string GetAttributeName<EventType>(EventType type) {
+
static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
"KEY_EXPIRED", "VENDOR_DEFINED",
"SESSION_RECLAIMED"};
- if (((size_t)type) >= arraysize(type_names)) {
+ if (attribute >= arraysize(type_names)) {
return "UNKNOWN_TYPE";
}
- return type_names[(size_t)type];
+ return type_names[attribute];
}
template <typename T>
@@ -87,14 +85,14 @@
template <typename T>
void ExportCounterMetricWithAttributeNames(
- const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
+ const android::CounterMetric<T> &counter, std::string typeName, PersistableBundle *metrics) {
if (!metrics) {
ALOGE("metrics was unexpectedly null.");
return;
}
- counter.ExportValues([&](const T &attribute, const int64_t value) {
+ counter.ExportValues([&](const uint32_t attribute, const int64_t value) {
std::string name = counter.metric_name() + "." +
- GetAttributeName(attribute) + ".count";
+ GetAttributeName(typeName, attribute) + ".count";
metrics->putLong(android::String16(name.c_str()), value);
});
}
@@ -196,8 +194,8 @@
ExportEventMetric(metrics.mProvideKeyResponseTimeUs, mBundle);
ExportCounterMetric(metrics.mGetProvisionRequestCounter, mBundle);
ExportCounterMetric(metrics.mProvideProvisionResponseCounter, mBundle);
- ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, mBundle);
- ExportCounterMetricWithAttributeNames(metrics.mEventCounter, mBundle);
+ ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, "KeyStatusChange", mBundle);
+ ExportCounterMetricWithAttributeNames(metrics.mEventCounter, "Event", mBundle);
ExportCounterMetric(metrics.mGetDeviceUniqueIdCounter, mBundle);
ExportSessionLifespans(metrics.GetSessionLifespans(), mBundle);
return android::OK;
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 0b117a3..bca292d 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -32,10 +32,10 @@
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/HidlSupport.h>
+#include <cutils/properties.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
-#include <cutils/properties.h>
#include <mediadrm/CryptoHal.h>
#include <mediadrm/DrmHal.h>
@@ -57,10 +57,10 @@
namespace {
-template<typename Hal>
-Hal *MakeObject(status_t *pstatus) {
+template <typename Hal>
+Hal* MakeObject(status_t* pstatus) {
status_t err = OK;
- status_t &status = pstatus ? *pstatus : err;
+ status_t& status = pstatus ? *pstatus : err;
auto obj = new Hal();
status = obj->initCheck();
if (status != OK && status != NO_INIT) {
@@ -70,43 +70,44 @@
}
template <typename Hal, typename V, typename M>
-void MakeHidlFactories(const uint8_t uuid[16], V &factories, M& instances) {
+void MakeHidlFactories(const uint8_t uuid[16], V& factories, M& instances) {
sp<HServiceManager> serviceManager = HServiceManager::getService();
if (serviceManager == nullptr) {
LOG2BE("Failed to get service manager");
return;
}
- serviceManager->listManifestByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> ®istered) {
- for (const auto &instance : registered) {
- auto factory = Hal::getService(instance);
- if (factory != nullptr) {
- instances[instance.c_str()] = Hal::descriptor;
- if (!uuid) {
- factories.push_back(factory);
- continue;
+ serviceManager->listManifestByInterface(
+ Hal::descriptor, [&](const hidl_vec<hidl_string>& registered) {
+ for (const auto& instance : registered) {
+ auto factory = Hal::getService(instance);
+ if (factory != nullptr) {
+ instances[instance.c_str()] = Hal::descriptor;
+ if (!uuid) {
+ factories.push_back(factory);
+ continue;
+ }
+ auto supported = factory->isCryptoSchemeSupported(uuid);
+ if (!supported.isOk()) {
+ LOG2BE(uuid, "isCryptoSchemeSupported txn failed: %s",
+ supported.description().c_str());
+ continue;
+ }
+ if (supported) {
+ factories.push_back(factory);
+ }
+ }
}
- auto supported = factory->isCryptoSchemeSupported(uuid);
- if (!supported.isOk()) {
- LOG2BE(uuid, "isCryptoSchemeSupported txn failed: %s",
- supported.description().c_str());
- continue;
- }
- if (supported) {
- factories.push_back(factory);
- }
- }
- }
- });
+ });
}
template <typename Hal, typename V>
-void MakeHidlFactories(const uint8_t uuid[16], V &factories) {
+void MakeHidlFactories(const uint8_t uuid[16], V& factories) {
std::map<std::string, std::string> instances;
MakeHidlFactories<Hal>(uuid, factories, instances);
}
-hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
+hidl_vec<uint8_t> toHidlVec(const void* ptr, size_t size) {
hidl_vec<uint8_t> vec(size);
if (ptr != nullptr) {
memcpy(vec.data(), ptr, size);
@@ -114,19 +115,19 @@
return vec;
}
-hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
+hidl_array<uint8_t, 16> toHidlArray16(const uint8_t* ptr) {
if (ptr == nullptr) {
return hidl_array<uint8_t, 16>();
}
return hidl_array<uint8_t, 16>(ptr);
}
-sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory> &factory,
- const uint8_t uuid[16], const char *appPackageName) {
+sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory>& factory, const uint8_t uuid[16],
+ const char* appPackageName) {
sp<::V1_0::IDrmPlugin> plugin;
auto err = factory->createPlugin(
toHidlArray16(uuid), hidl_string(appPackageName),
- [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
+ [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin>& hPlugin) {
if (status != ::V1_0::Status::OK) {
LOG2BE(uuid, "MakeDrmPlugin failed: %d", status);
return;
@@ -141,13 +142,13 @@
}
}
-sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory> &factory,
- const uint8_t uuid[16], const void *initData,
+sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void* initData,
size_t initDataSize) {
sp<::V1_0::ICryptoPlugin> plugin;
auto err = factory->createPlugin(
toHidlArray16(uuid), toHidlVec(initData, initDataSize),
- [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
+ [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin>& hPlugin) {
if (status != ::V1_0::Status::OK) {
LOG2BE(uuid, "MakeCryptoPlugin failed: %d", status);
return;
@@ -162,17 +163,17 @@
}
}
-} // namespace
+} // namespace
bool UseDrmService() {
return property_get_bool("mediadrm.use_mediadrmserver", true);
}
-sp<IDrm> MakeDrm(status_t *pstatus) {
+sp<IDrm> MakeDrm(status_t* pstatus) {
return MakeObject<DrmHal>(pstatus);
}
-sp<ICrypto> MakeCrypto(status_t *pstatus) {
+sp<ICrypto> MakeCrypto(status_t* pstatus) {
return MakeObject<CryptoHal>(pstatus);
}
@@ -191,9 +192,9 @@
}
std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
- const char *appPackageName) {
+ const char* appPackageName) {
std::vector<sp<::V1_0::IDrmPlugin>> plugins;
- for (const auto &factory : MakeDrmFactories(uuid)) {
+ for (const auto& factory : MakeDrmFactories(uuid)) {
plugins.push_back(MakeDrmPlugin(factory, uuid, appPackageName));
}
return plugins;
@@ -209,10 +210,11 @@
return cryptoFactories;
}
-std::vector<sp<ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16], const void *initData,
- size_t initDataSize) {
- std::vector<sp<ICryptoPlugin>> plugins;
- for (const auto &factory : MakeCryptoFactories(uuid)) {
+std::vector<sp<::V1_0::ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16],
+ const void* initData,
+ size_t initDataSize) {
+ std::vector<sp<::V1_0::ICryptoPlugin>> plugins;
+ for (const auto& factory : MakeCryptoFactories(uuid)) {
plugins.push_back(MakeCryptoPlugin(factory, uuid, initData, initDataSize));
}
return plugins;
@@ -220,90 +222,90 @@
status_t toStatusT_1_4(::V1_4::Status status) {
switch (status) {
- case ::V1_4::Status::OK:
- return OK;
- case ::V1_4::Status::BAD_VALUE:
- return BAD_VALUE;
- case ::V1_4::Status::ERROR_DRM_CANNOT_HANDLE:
- return ERROR_DRM_CANNOT_HANDLE;
- case ::V1_4::Status::ERROR_DRM_DECRYPT:
- return ERROR_DRM_DECRYPT;
- case ::V1_4::Status::ERROR_DRM_DEVICE_REVOKED:
- return ERROR_DRM_DEVICE_REVOKED;
- case ::V1_4::Status::ERROR_DRM_FRAME_TOO_LARGE:
- return ERROR_DRM_FRAME_TOO_LARGE;
- case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
- return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
- case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_SECURITY:
- return ERROR_DRM_INSUFFICIENT_SECURITY;
- case ::V1_4::Status::ERROR_DRM_INVALID_STATE:
- return ERROR_DRM_INVALID_STATE;
- case ::V1_4::Status::ERROR_DRM_LICENSE_EXPIRED:
- return ERROR_DRM_LICENSE_EXPIRED;
- case ::V1_4::Status::ERROR_DRM_NO_LICENSE:
- return ERROR_DRM_NO_LICENSE;
- case ::V1_4::Status::ERROR_DRM_NOT_PROVISIONED:
- return ERROR_DRM_NOT_PROVISIONED;
- case ::V1_4::Status::ERROR_DRM_RESOURCE_BUSY:
- return ERROR_DRM_RESOURCE_BUSY;
- case ::V1_4::Status::ERROR_DRM_RESOURCE_CONTENTION:
- return ERROR_DRM_RESOURCE_CONTENTION;
- case ::V1_4::Status::ERROR_DRM_SESSION_LOST_STATE:
- return ERROR_DRM_SESSION_LOST_STATE;
- case ::V1_4::Status::ERROR_DRM_SESSION_NOT_OPENED:
- return ERROR_DRM_SESSION_NOT_OPENED;
+ case ::V1_4::Status::OK:
+ return OK;
+ case ::V1_4::Status::BAD_VALUE:
+ return BAD_VALUE;
+ case ::V1_4::Status::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ case ::V1_4::Status::ERROR_DRM_DECRYPT:
+ return ERROR_DRM_DECRYPT;
+ case ::V1_4::Status::ERROR_DRM_DEVICE_REVOKED:
+ return ERROR_DRM_DEVICE_REVOKED;
+ case ::V1_4::Status::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ case ::V1_4::Status::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ case ::V1_4::Status::ERROR_DRM_INVALID_STATE:
+ return ERROR_DRM_INVALID_STATE;
+ case ::V1_4::Status::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ case ::V1_4::Status::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ case ::V1_4::Status::ERROR_DRM_NOT_PROVISIONED:
+ return ERROR_DRM_NOT_PROVISIONED;
+ case ::V1_4::Status::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ case ::V1_4::Status::ERROR_DRM_RESOURCE_CONTENTION:
+ return ERROR_DRM_RESOURCE_CONTENTION;
+ case ::V1_4::Status::ERROR_DRM_SESSION_LOST_STATE:
+ return ERROR_DRM_SESSION_LOST_STATE;
+ case ::V1_4::Status::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
- // New in S / drm@1.4:
- case ::V1_4::Status::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
- return ERROR_DRM_ZERO_SUBSAMPLES;
- case ::V1_4::Status::CRYPTO_LIBRARY_ERROR:
- return ERROR_DRM_CRYPTO_LIBRARY;
- case ::V1_4::Status::GENERAL_OEM_ERROR:
- return ERROR_DRM_GENERIC_OEM;
- case ::V1_4::Status::GENERAL_PLUGIN_ERROR:
- return ERROR_DRM_GENERIC_PLUGIN;
- case ::V1_4::Status::INIT_DATA_INVALID:
- return ERROR_DRM_INIT_DATA;
- case ::V1_4::Status::KEY_NOT_LOADED:
- return ERROR_DRM_KEY_NOT_LOADED;
- case ::V1_4::Status::LICENSE_PARSE_ERROR:
- return ERROR_DRM_LICENSE_PARSE;
- case ::V1_4::Status::LICENSE_POLICY_ERROR:
- return ERROR_DRM_LICENSE_POLICY;
- case ::V1_4::Status::LICENSE_RELEASE_ERROR:
- return ERROR_DRM_LICENSE_RELEASE;
- case ::V1_4::Status::LICENSE_REQUEST_REJECTED:
- return ERROR_DRM_LICENSE_REQUEST_REJECTED;
- case ::V1_4::Status::LICENSE_RESTORE_ERROR:
- return ERROR_DRM_LICENSE_RESTORE;
- case ::V1_4::Status::LICENSE_STATE_ERROR:
- return ERROR_DRM_LICENSE_STATE;
- case ::V1_4::Status::MALFORMED_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MALFORMED;
- case ::V1_4::Status::MEDIA_FRAMEWORK_ERROR:
- return ERROR_DRM_MEDIA_FRAMEWORK;
- case ::V1_4::Status::MISSING_CERTIFICATE:
- return ERROR_DRM_CERTIFICATE_MISSING;
- case ::V1_4::Status::PROVISIONING_CERTIFICATE_ERROR:
- return ERROR_DRM_PROVISIONING_CERTIFICATE;
- case ::V1_4::Status::PROVISIONING_CONFIGURATION_ERROR:
- return ERROR_DRM_PROVISIONING_CONFIG;
- case ::V1_4::Status::PROVISIONING_PARSE_ERROR:
- return ERROR_DRM_PROVISIONING_PARSE;
- case ::V1_4::Status::PROVISIONING_REQUEST_REJECTED:
- return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
- case ::V1_4::Status::RETRYABLE_PROVISIONING_ERROR:
- return ERROR_DRM_PROVISIONING_RETRY;
- case ::V1_4::Status::SECURE_STOP_RELEASE_ERROR:
- return ERROR_DRM_SECURE_STOP_RELEASE;
- case ::V1_4::Status::STORAGE_READ_FAILURE:
- return ERROR_DRM_STORAGE_READ;
- case ::V1_4::Status::STORAGE_WRITE_FAILURE:
- return ERROR_DRM_STORAGE_WRITE;
+ // New in S / drm@1.4:
+ case ::V1_4::Status::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ return ERROR_DRM_ZERO_SUBSAMPLES;
+ case ::V1_4::Status::CRYPTO_LIBRARY_ERROR:
+ return ERROR_DRM_CRYPTO_LIBRARY;
+ case ::V1_4::Status::GENERAL_OEM_ERROR:
+ return ERROR_DRM_GENERIC_OEM;
+ case ::V1_4::Status::GENERAL_PLUGIN_ERROR:
+ return ERROR_DRM_GENERIC_PLUGIN;
+ case ::V1_4::Status::INIT_DATA_INVALID:
+ return ERROR_DRM_INIT_DATA;
+ case ::V1_4::Status::KEY_NOT_LOADED:
+ return ERROR_DRM_KEY_NOT_LOADED;
+ case ::V1_4::Status::LICENSE_PARSE_ERROR:
+ return ERROR_DRM_LICENSE_PARSE;
+ case ::V1_4::Status::LICENSE_POLICY_ERROR:
+ return ERROR_DRM_LICENSE_POLICY;
+ case ::V1_4::Status::LICENSE_RELEASE_ERROR:
+ return ERROR_DRM_LICENSE_RELEASE;
+ case ::V1_4::Status::LICENSE_REQUEST_REJECTED:
+ return ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ case ::V1_4::Status::LICENSE_RESTORE_ERROR:
+ return ERROR_DRM_LICENSE_RESTORE;
+ case ::V1_4::Status::LICENSE_STATE_ERROR:
+ return ERROR_DRM_LICENSE_STATE;
+ case ::V1_4::Status::MALFORMED_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MALFORMED;
+ case ::V1_4::Status::MEDIA_FRAMEWORK_ERROR:
+ return ERROR_DRM_MEDIA_FRAMEWORK;
+ case ::V1_4::Status::MISSING_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MISSING;
+ case ::V1_4::Status::PROVISIONING_CERTIFICATE_ERROR:
+ return ERROR_DRM_PROVISIONING_CERTIFICATE;
+ case ::V1_4::Status::PROVISIONING_CONFIGURATION_ERROR:
+ return ERROR_DRM_PROVISIONING_CONFIG;
+ case ::V1_4::Status::PROVISIONING_PARSE_ERROR:
+ return ERROR_DRM_PROVISIONING_PARSE;
+ case ::V1_4::Status::PROVISIONING_REQUEST_REJECTED:
+ return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+ case ::V1_4::Status::RETRYABLE_PROVISIONING_ERROR:
+ return ERROR_DRM_PROVISIONING_RETRY;
+ case ::V1_4::Status::SECURE_STOP_RELEASE_ERROR:
+ return ERROR_DRM_SECURE_STOP_RELEASE;
+ case ::V1_4::Status::STORAGE_READ_FAILURE:
+ return ERROR_DRM_STORAGE_READ;
+ case ::V1_4::Status::STORAGE_WRITE_FAILURE:
+ return ERROR_DRM_STORAGE_WRITE;
- case ::V1_4::Status::ERROR_DRM_UNKNOWN:
- default:
- return ERROR_DRM_UNKNOWN;
+ case ::V1_4::Status::ERROR_DRM_UNKNOWN:
+ default:
+ return ERROR_DRM_UNKNOWN;
}
return ERROR_DRM_UNKNOWN;
}
@@ -312,20 +314,34 @@
char logPriorityToChar(::V1_4::LogPriority priority) {
char p = 'U';
switch (priority) {
- case ::V1_4::LogPriority::VERBOSE: p = 'V'; break;
- case ::V1_4::LogPriority::DEBUG: p = 'D'; break;
- case ::V1_4::LogPriority::INFO: p = 'I'; break;
- case ::V1_4::LogPriority::WARN: p = 'W'; break;
- case ::V1_4::LogPriority::ERROR: p = 'E'; break;
- case ::V1_4::LogPriority::FATAL: p = 'F'; break;
- default: p = 'U'; break;
+ case ::V1_4::LogPriority::VERBOSE:
+ p = 'V';
+ break;
+ case ::V1_4::LogPriority::DEBUG:
+ p = 'D';
+ break;
+ case ::V1_4::LogPriority::INFO:
+ p = 'I';
+ break;
+ case ::V1_4::LogPriority::WARN:
+ p = 'W';
+ break;
+ case ::V1_4::LogPriority::ERROR:
+ p = 'E';
+ break;
+ case ::V1_4::LogPriority::FATAL:
+ p = 'F';
+ break;
+ default:
+ p = 'U';
+ break;
}
return p;
}
} // namespace
-std::string GetExceptionMessage(status_t err, const char *msg,
- const Vector<::V1_4::LogMessage> &logs) {
+std::string GetExceptionMessage(status_t err, const char* msg,
+ const Vector<::V1_4::LogMessage>& logs) {
std::string ruler("==============================");
std::string header("Beginning of DRM Plugin Log");
std::string footer("End of DRM Plugin Log");
@@ -355,7 +371,7 @@
return msg8.c_str();
}
-void LogBuffer::addLog(const ::V1_4::LogMessage &log) {
+void LogBuffer::addLog(const ::V1_4::LogMessage& log) {
std::unique_lock<std::mutex> lock(mMutex);
mBuffer.push_back(log);
while (mBuffer.size() > MAX_CAPACITY) {
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index 49bbad4..a85e3cf 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -36,6 +36,7 @@
"libmediadrm",
"liblog",
"resourcemanager_aidl_interface-ndk",
+ "libaidlcommonsupport",
],
header_libs: [
"libmedia_headers",
@@ -59,6 +60,7 @@
"android.hardware.drm@1.4",
"libhidlallocatorutils",
"libhidlbase",
+ "android.hardware.drm-V1-ndk",
],
fuzz_config: {
cc: [
diff --git a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
index 8df0477..eabd41f 100644
--- a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
+++ b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
@@ -24,6 +24,8 @@
#include <mediadrm/DrmHal.h>
#include <utils/String8.h>
#include "fuzzer/FuzzedDataProvider.h"
+#include <binder/PersistableBundle.h>
+#include <android/hardware/drm/1.0/types.h>
#define AES_BLOCK_SIZE 16
#define UNUSED_PARAM __attribute__((unused))
@@ -33,6 +35,7 @@
using android::hardware::fromHeap;
using ::android::os::PersistableBundle;
using drm::V1_0::BufferType;
+using ::android::hardware::drm::V1_0::DestinationBuffer;
enum {
INVALID_UUID = 0,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 5fd39e6..5be59f0 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -15,25 +15,12 @@
*/
#ifndef CRYPTO_HAL_H_
-
#define CRYPTO_HAL_H_
-#include <android/hardware/drm/1.0/ICryptoFactory.h>
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.1/ICryptoFactory.h>
-#include <android/hardware/drm/1.2/ICryptoPlugin.h>
-#include <android/hardware/drm/1.4/ICryptoPlugin.h>
-
#include <mediadrm/ICrypto.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::ICryptoFactory;
-using drm::V1_0::ICryptoPlugin;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::DestinationBuffer;
-
using ::android::hardware::HidlMemory;
class IMemoryHeap;
@@ -43,67 +30,30 @@
struct CryptoHal : public ICrypto {
CryptoHal();
virtual ~CryptoHal();
-
virtual status_t initCheck() const;
-
virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
-
virtual status_t createPlugin(
const uint8_t uuid[16], const void *data, size_t size);
-
virtual status_t destroyPlugin();
-
virtual bool requiresSecureDecoderComponent(
const char *mime) const;
-
virtual void notifyResolution(uint32_t width, uint32_t height);
-
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
-
virtual ssize_t 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 drm::V1_0::SharedBuffer &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const ::DestinationBuffer &destination,
+ const drm::V1_0::DestinationBuffer &destination,
AString *errorDetailMsg);
-
- virtual int32_t setHeap(const sp<HidlMemory>& heap) {
- return setHeapBase(heap);
- }
- virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
-
+ virtual int32_t setHeap(const sp<HidlMemory>& heap);
+ virtual void unsetHeap(int32_t seqNum);
virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
-
private:
- mutable Mutex mLock;
-
- const Vector<sp<ICryptoFactory>> mFactories;
- sp<ICryptoPlugin> mPlugin;
- sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
-
- /**
- * mInitCheck is:
- * NO_INIT if a plugin hasn't been created yet
- * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
- * OK after a plugin has been created and mPlugin is valid
- */
- status_t mInitCheck;
-
- KeyedVector<int32_t, size_t> mHeapSizes;
- int32_t mHeapSeqNum;
-
- Vector<sp<ICryptoFactory>> makeCryptoFactories();
- sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
- const uint8_t uuid[16], const void *initData, size_t size);
-
- int32_t setHeapBase(const sp<HidlMemory>& heap);
- void clearHeapBase(int32_t seqNum);
-
- status_t checkSharedBuffer(const ::SharedBuffer& buffer);
-
+ sp<ICrypto> mCryptoHalHidl;
+ sp<ICrypto> mCryptoHalAidl;
DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
};
-} // namespace android
+}
-#endif // CRYPTO_HAL_H_
+#endif
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
new file mode 100644
index 0000000..a25b091
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CRYPTO_HAL_AIDL_H_
+#define CRYPTO_HAL_AIDL_H_
+
+#include <aidl/android/hardware/drm/ICryptoFactory.h>
+#include <aidl/android/hardware/drm/ICryptoPlugin.h>
+
+#include <mediadrm/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+using ICryptoFactoryAidl = ::aidl::android::hardware::drm::ICryptoFactory;
+using ICryptoPluginAidl = ::aidl::android::hardware::drm::ICryptoPlugin;
+using ::aidl::android::hardware::drm::Uuid;
+
+// -------Hidl interface related-----------------
+// TODO: replace before removing hidl interface
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::SharedBuffer;
+
+using ::android::hardware::HidlMemory;
+
+// -------Hidl interface related end-------------
+
+class IMemoryHeap;
+
+namespace android {
+
+struct CryptoHalAidl : public ICrypto {
+ CryptoHalAidl();
+ virtual ~CryptoHalAidl();
+ virtual status_t initCheck() const;
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+ virtual status_t createPlugin(const uint8_t uuid[16], const void* data, size_t size);
+ virtual status_t destroyPlugin();
+ virtual bool requiresSecureDecoderComponent(const char* mime) const;
+ virtual void notifyResolution(uint32_t width, uint32_t height);
+ virtual status_t setMediaDrmSession(const Vector<uint8_t>& sessionId);
+ virtual ssize_t 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);
+ virtual int32_t setHeap(const sp<HidlMemory>& heap);
+ virtual void unsetHeap(int32_t seqNum);
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+
+ private:
+ mutable Mutex mLock;
+
+ const std::vector<std::shared_ptr<ICryptoFactoryAidl>> mFactories;
+ std::shared_ptr<ICryptoPluginAidl> mPlugin;
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ KeyedVector<int32_t, size_t> mHeapSizes;
+ int32_t mHeapSeqNum;
+
+ std::vector<std::shared_ptr<ICryptoFactoryAidl>> makeCryptoFactories();
+ std::shared_ptr<ICryptoPluginAidl> makeCryptoPlugin(
+ const std::shared_ptr<ICryptoFactoryAidl>& factory, const Uuid& uuidAidl,
+ const std::vector<uint8_t> initData);
+
+ status_t checkSharedBuffer(const ::SharedBuffer& buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(CryptoHalAidl);
+};
+
+} // namespace android
+
+#endif // CRYPTO_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
new file mode 100644
index 0000000..6db1e89
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CRYPTO_HAL_HIDL_H_
+#define CRYPTO_HAL_HIDL_H_
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
+#include <android/hardware/drm/1.4/ICryptoPlugin.h>
+
+#include <mediadrm/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::ICryptoFactory;
+using drm::V1_0::ICryptoPlugin;
+using drm::V1_0::SharedBuffer;
+using drm::V1_0::DestinationBuffer;
+
+using ::android::hardware::HidlMemory;
+
+class IMemoryHeap;
+
+namespace android {
+
+struct CryptoHalHidl : public ICrypto {
+ CryptoHalHidl();
+ virtual ~CryptoHalHidl();
+
+ virtual status_t initCheck() const;
+
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
+
+ virtual status_t createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size);
+
+ virtual status_t destroyPlugin();
+
+ virtual bool requiresSecureDecoderComponent(
+ const char *mime) const;
+
+ virtual void notifyResolution(uint32_t width, uint32_t height);
+
+ virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+
+ virtual ssize_t 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);
+
+ virtual int32_t setHeap(const sp<HidlMemory>& heap) {
+ return setHeapBase(heap);
+ }
+ virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
+
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+
+private:
+ mutable Mutex mLock;
+
+ const Vector<sp<ICryptoFactory>> mFactories;
+ sp<ICryptoPlugin> mPlugin;
+ sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ KeyedVector<int32_t, size_t> mHeapSizes;
+ int32_t mHeapSeqNum;
+
+ Vector<sp<ICryptoFactory>> makeCryptoFactories();
+ sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
+ const uint8_t uuid[16], const void *initData, size_t size);
+
+ int32_t setHeapBase(const sp<HidlMemory>& heap);
+ void clearHeapBase(int32_t seqNum);
+
+ status_t checkSharedBuffer(const ::SharedBuffer& buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(CryptoHalHidl);
+};
+
+} // namespace android
+
+#endif // CRYPTO_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index 7eb1dec..bb58585 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -14,77 +14,27 @@
* limitations under the License.
*/
-#ifndef DRM_HAL_H_
-
-#define DRM_HAL_H_
-
-#include <android/hardware/drm/1.0/IDrmFactory.h>
-#include <android/hardware/drm/1.0/IDrmPlugin.h>
-#include <android/hardware/drm/1.1/IDrmFactory.h>
-#include <android/hardware/drm/1.1/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmFactory.h>
-#include <android/hardware/drm/1.2/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmPluginListener.h>
-#include <android/hardware/drm/1.4/IDrmPlugin.h>
-#include <android/hardware/drm/1.4/types.h>
-
-#include <media/drm/DrmAPI.h>
-#include <mediadrm/DrmMetrics.h>
-#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/IDrm.h>
-#include <mediadrm/IDrmClient.h>
-#include <mediadrm/IDrmMetricsConsumer.h>
-#include <utils/threads.h>
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::EventType;
-using drm::V1_0::IDrmFactory;
-using drm::V1_0::IDrmPlugin;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeyStatus;
-using drm::V1_2::OfflineLicenseState;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
-typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
+#ifndef DRM_HAL_H_
+#define DRM_HAL_H_
namespace android {
-struct DrmSessionClientInterface;
-
-inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
- if (l.size() != r.size()) return false;
- return memcmp(l.array(), r.array(), l.size()) == 0;
-}
-
-struct DrmHal : public IDrm,
- public IDrmPluginListener_V1_2 {
-
- struct DrmSessionClient;
-
+struct DrmHal : public IDrm {
DrmHal();
virtual ~DrmHal();
-
virtual status_t initCheck() const;
-
virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
- const String8& mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported);
-
+ const String8 &mimeType,
+ DrmPlugin::SecurityLevel securityLevel,
+ bool *result);
virtual status_t createPlugin(const uint8_t uuid[16],
const String8 &appPackageName);
-
virtual status_t destroyPlugin();
-
- virtual status_t openSession(DrmPlugin::SecurityLevel level,
+ virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
Vector<uint8_t> &sessionId);
-
virtual status_t closeSession(Vector<uint8_t> const &sessionId);
-
virtual status_t
getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData,
@@ -92,168 +42,88 @@
KeyedVector<String8, String8> const &optionalParameters,
Vector<uint8_t> &request, String8 &defaultUrl,
DrmPlugin::KeyRequestType *keyRequestType);
-
virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &response,
Vector<uint8_t> &keySetId);
-
virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
-
virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keySetId);
-
virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
KeyedVector<String8, String8> &infoMap) const;
-
virtual status_t getProvisionRequest(String8 const &certType,
String8 const &certAuthority,
Vector<uint8_t> &request,
- String8 &defaulUrl);
-
+ String8 &defaultUrl);
virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey);
-
virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
-
virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
virtual status_t removeAllSecureStops();
-
virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
DrmPlugin::HdcpLevel *maxLevel) const;
virtual status_t getNumberOfSessions(uint32_t *currentSessions,
uint32_t *maxSessions) const;
virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
DrmPlugin::SecurityLevel *level) const;
-
virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
DrmPlugin::OfflineLicenseState *licenseState) const;
-
- virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+ virtual status_t getPropertyString(String8 const &name, String8 &value) const;
virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value ) const;
- virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
+ Vector<uint8_t> &value) const;
+ virtual status_t setPropertyString(String8 const &name,
+ String8 const &value ) const;
virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const;
+ Vector<uint8_t> const &value) const;
virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
-
virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
String8 const &algorithm);
-
virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
String8 const &algorithm);
-
virtual status_t encrypt(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &input,
Vector<uint8_t> const &iv,
Vector<uint8_t> &output);
-
virtual status_t decrypt(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &input,
Vector<uint8_t> const &iv,
Vector<uint8_t> &output);
-
virtual status_t sign(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &message,
Vector<uint8_t> &signature);
-
virtual status_t verify(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &keyId,
Vector<uint8_t> const &message,
Vector<uint8_t> const &signature,
bool &match);
-
virtual status_t signRSA(Vector<uint8_t> const &sessionId,
String8 const &algorithm,
Vector<uint8_t> const &message,
Vector<uint8_t> const &wrappedKey,
Vector<uint8_t> &signature);
-
virtual status_t setListener(const sp<IDrmClient>& listener);
-
virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
-
virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
bool *required) const;
-
virtual status_t setPlaybackId(
Vector<uint8_t> const &sessionId,
const char *playbackId);
-
virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
- // Methods of IDrmPluginListener
- Return<void> sendEvent(EventType eventType,
- const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
-
- Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
- int64_t expiryTimeInMS);
-
- Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
-
- Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
-
- Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
-
private:
- static Mutex mLock;
-
- sp<IDrmClient> mListener;
- mutable Mutex mEventLock;
- mutable Mutex mNotifyLock;
-
- const std::vector<sp<IDrmFactory>> mFactories;
- sp<IDrmPlugin> mPlugin;
- sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
- sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
- sp<drm::V1_4::IDrmPlugin> mPluginV1_4;
- String8 mAppPackageName;
-
- // Mutable to allow modification within GetPropertyByteArray.
- mutable MediaDrmMetrics mMetrics;
-
- std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
- void closeOpenSessions();
- void cleanup();
-
- /**
- * mInitCheck is:
- * NO_INIT if a plugin hasn't been created yet
- * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
- * OK after a plugin has been created and mPlugin is valid
- */
- status_t mInitCheck;
-
- std::vector<sp<IDrmFactory>> makeDrmFactories();
- sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
- const uint8_t uuid[16], const String8& appPackageName);
-
- void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
-
- std::string reportPluginMetrics() const;
- std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
- status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
- status_t getPropertyByteArrayInternal(String8 const &name,
- Vector<uint8_t> &value) const;
- status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
- const uint8_t uuid[16],
- const String8 &mimeType,
- DrmPlugin::SecurityLevel level,
- bool *isSupported);
-
+ sp<IDrm> mDrmHalHidl;
+ std::shared_ptr<IDrm> mDrmHalAidl;
DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
};
-} // namespace android
+} // namespace android
-#endif // DRM_HAL_H_
+#endif
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
new file mode 100644
index 0000000..6720734
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_HAL_AIDL_H_
+#define DRM_HAL_AIDL_H_
+
+#include <aidl/android/hardware/drm/BnDrmPluginListener.h>
+#include <aidl/android/hardware/drm/IDrmFactory.h>
+#include <aidl/android/hardware/drm/IDrmPlugin.h>
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <mediadrm/DrmMetrics.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrm.h>
+#include <memory>
+
+using ::aidl::android::hardware::drm::BnDrmPluginListener;
+using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
+using IDrmFactoryAidl = ::aidl::android::hardware::drm::IDrmFactory;
+using EventTypeAidl = ::aidl::android::hardware::drm::EventType;
+using KeyStatusAidl = ::aidl::android::hardware::drm::KeyStatus;
+using ::aidl::android::hardware::drm::Uuid;
+
+namespace android {
+struct DrmHalAidl : public IDrm,
+ public BnDrmPluginListener,
+ std::enable_shared_from_this<BnDrmPluginListener> {
+ struct DrmSessionClient;
+ DrmHalAidl();
+ virtual ~DrmHalAidl();
+ virtual status_t initCheck() const;
+ virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+ DrmPlugin::SecurityLevel securityLevel, bool* result);
+ virtual status_t createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+ virtual status_t destroyPlugin();
+ virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+ Vector<uint8_t>& sessionId);
+ virtual status_t closeSession(Vector<uint8_t> const& sessionId);
+ virtual status_t getKeyRequest(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& initData, String8 const& mimeType,
+ DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const& optionalParameters,
+ Vector<uint8_t>& request, String8& defaultUrl,
+ DrmPlugin::KeyRequestType* keyRequestType);
+ virtual status_t provideKeyResponse(Vector<uint8_t> const& sessionId,
+ Vector<uint8_t> const& response, Vector<uint8_t>& keySetId);
+ virtual status_t removeKeys(Vector<uint8_t> const& keySetId);
+ virtual status_t restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId);
+ virtual status_t queryKeyStatus(Vector<uint8_t> const& sessionId,
+ KeyedVector<String8, String8>& infoMap) const;
+ virtual status_t getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+ Vector<uint8_t>& request, String8& defaultUrl);
+ virtual status_t provideProvisionResponse(Vector<uint8_t> const& response,
+ Vector<uint8_t>& certificate,
+ Vector<uint8_t>& wrappedKey);
+ virtual status_t getSecureStops(List<Vector<uint8_t>>& secureStops);
+ virtual status_t getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+ virtual status_t getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+ virtual status_t releaseSecureStops(Vector<uint8_t> const& ssRelease);
+ virtual status_t removeSecureStop(Vector<uint8_t> const& ssid);
+ virtual status_t removeAllSecureStops();
+ virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+ DrmPlugin::HdcpLevel* maxLevel) const;
+ virtual status_t getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+ virtual status_t getSecurityLevel(Vector<uint8_t> const& sessionId,
+ DrmPlugin::SecurityLevel* level) const;
+ virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+ virtual status_t removeOfflineLicense(Vector<uint8_t> const& keySetId);
+ virtual status_t getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+ DrmPlugin::OfflineLicenseState* licenseState) const;
+ virtual status_t getPropertyString(String8 const& name, String8& value) const;
+ virtual status_t getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+ virtual status_t setPropertyString(String8 const& name, String8 const& value) const;
+ virtual status_t setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+ virtual status_t getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+ virtual status_t setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+ virtual status_t setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+ virtual status_t encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual status_t decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+ Vector<uint8_t>& output);
+ virtual status_t sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+ virtual status_t verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+ bool& match);
+ virtual status_t signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+ Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+ Vector<uint8_t>& signature);
+ virtual status_t setListener(const sp<IDrmClient>& listener);
+ virtual status_t requiresSecureDecoder(const char* mime, bool* required) const;
+ virtual status_t requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+ bool* required) const;
+ virtual status_t setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+ // Methods of IDrmPluginListenerAidl
+ ::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
+ const std::vector<uint8_t>& in_sessionId,
+ const std::vector<uint8_t>& in_data);
+ ::ndk::ScopedAStatus onExpirationUpdate(const std::vector<uint8_t>& in_sessionId,
+ int64_t in_expiryTimeInMS);
+ ::ndk::ScopedAStatus onKeysChange(const std::vector<uint8_t>& in_sessionId,
+ const std::vector<KeyStatusAidl>& in_keyStatusList,
+ bool in_hasNewUsableKey);
+ ::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
+
+ private:
+ static Mutex mLock;
+ sp<IDrmClient> mListener;
+ mutable Mutex mEventLock;
+ mutable Mutex mNotifyLock;
+ const std::vector<std::shared_ptr<IDrmFactoryAidl>> mFactories;
+ std::shared_ptr<IDrmPluginAidl> mPlugin;
+ std::vector<std::shared_ptr<IDrmFactoryAidl>> makeDrmFactories();
+ status_t mInitCheck;
+ mutable MediaDrmMetrics mMetrics;
+ std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
+ void cleanup();
+ void closeOpenSessions();
+ std::string reportPluginMetrics() const;
+ std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
+ status_t getPropertyStringInternal(String8 const& name, String8& value) const;
+ status_t getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
+ DISALLOW_EVIL_CONSTRUCTORS(DrmHalAidl);
+};
+
+} // namespace android
+
+#endif
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
new file mode 100644
index 0000000..91dc700
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_HAL_HIDL_H_
+#define DRM_HAL_HIDL_H_
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
+#include <android/hardware/drm/1.4/IDrmPlugin.h>
+#include <android/hardware/drm/1.4/types.h>
+
+#include <media/drm/DrmAPI.h>
+#include <mediadrm/DrmMetrics.h>
+#include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/threads.h>
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::EventType;
+using drm::V1_0::IDrmFactory;
+using drm::V1_0::IDrmPlugin;
+using drm::V1_0::IDrmPluginListener;
+using drm::V1_1::SecurityLevel;
+using drm::V1_2::KeyStatus;
+using drm::V1_2::OfflineLicenseState;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+typedef drm::V1_0::KeyStatus KeyStatus_V1_0;
+
+namespace android {
+
+struct DrmSessionClientInterface;
+
+inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) {
+ if (l.size() != r.size()) return false;
+ return memcmp(l.array(), r.array(), l.size()) == 0;
+}
+
+struct DrmHalHidl : public IDrm,
+ public IDrmPluginListener_V1_2 {
+
+ struct DrmSessionClient;
+
+ DrmHalHidl();
+ virtual ~DrmHalHidl();
+
+ virtual status_t initCheck() const;
+
+ virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
+ const String8& mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool *isSupported);
+
+ virtual status_t createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
+
+ virtual status_t destroyPlugin();
+
+ virtual status_t openSession(DrmPlugin::SecurityLevel level,
+ Vector<uint8_t> &sessionId);
+
+ virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+
+ virtual status_t
+ getKeyRequest(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &initData,
+ String8 const &mimeType, DrmPlugin::KeyType keyType,
+ KeyedVector<String8, String8> const &optionalParameters,
+ Vector<uint8_t> &request, String8 &defaultUrl,
+ DrmPlugin::KeyRequestType *keyRequestType);
+
+ virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response,
+ Vector<uint8_t> &keySetId);
+
+ virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+
+ virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId);
+
+ virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const;
+
+ virtual status_t getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority,
+ Vector<uint8_t> &request,
+ String8 &defaultUrl);
+
+ virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey);
+
+ virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
+ virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+ virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+
+ virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
+ virtual status_t removeAllSecureStops();
+
+ virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+ DrmPlugin::HdcpLevel *maxLevel) const;
+ virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+ uint32_t *maxSessions) const;
+ virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+ DrmPlugin::SecurityLevel *level) const;
+
+ virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+ virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
+ virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+ DrmPlugin::OfflineLicenseState *licenseState) const;
+
+ virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
+ virtual status_t getPropertyByteArray(String8 const &name,
+ Vector<uint8_t> &value ) const;
+ virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
+ virtual status_t setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const;
+ virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+
+ virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+
+ virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm);
+
+ virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual status_t decrypt(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv,
+ Vector<uint8_t> &output);
+
+ virtual status_t sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature);
+
+ virtual status_t verify(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &signature,
+ bool &match);
+
+ virtual status_t signRSA(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey,
+ Vector<uint8_t> &signature);
+
+ virtual status_t setListener(const sp<IDrmClient>& listener);
+
+ virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
+
+ virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
+ bool *required) const;
+
+ virtual status_t setPlaybackId(
+ Vector<uint8_t> const &sessionId,
+ const char *playbackId);
+
+ virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+
+ // Methods of IDrmPluginListener
+ Return<void> sendEvent(EventType eventType,
+ const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data);
+
+ Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+ int64_t expiryTimeInMS);
+
+ Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus_V1_0>& keyStatusList, bool hasNewUsableKey);
+
+ Return<void> sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
+
+ Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
+
+private:
+ static Mutex mLock;
+
+ sp<IDrmClient> mListener;
+ mutable Mutex mEventLock;
+ mutable Mutex mNotifyLock;
+
+ const std::vector<sp<IDrmFactory>> mFactories;
+ sp<IDrmPlugin> mPlugin;
+ sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
+ sp<drm::V1_2::IDrmPlugin> mPluginV1_2;
+ sp<drm::V1_4::IDrmPlugin> mPluginV1_4;
+ String8 mAppPackageName;
+
+ // Mutable to allow modification within GetPropertyByteArray.
+ mutable MediaDrmMetrics mMetrics;
+
+ std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
+ void closeOpenSessions();
+ void cleanup();
+
+ /**
+ * mInitCheck is:
+ * NO_INIT if a plugin hasn't been created yet
+ * ERROR_UNSUPPORTED if a plugin can't be created for the uuid
+ * OK after a plugin has been created and mPlugin is valid
+ */
+ status_t mInitCheck;
+
+ std::vector<sp<IDrmFactory>> makeDrmFactories();
+ sp<IDrmPlugin> makeDrmPlugin(const sp<IDrmFactory>& factory,
+ const uint8_t uuid[16], const String8& appPackageName);
+
+ void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
+
+ std::string reportPluginMetrics() const;
+ std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
+ status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
+ status_t getPropertyByteArrayInternal(String8 const &name,
+ Vector<uint8_t> &value) const;
+ status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
+ const uint8_t uuid[16],
+ const String8 &mimeType,
+ DrmPlugin::SecurityLevel level,
+ bool *isSupported);
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmHalHidl);
+};
+
+} // namespace android
+
+#endif // DRM_HAL_H_
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetrics.h b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
index 100b8f7..e1775c7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetrics.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
@@ -50,12 +50,10 @@
CounterMetric<status_t> mGetProvisionRequestCounter;
// Count of provideProvisionResponse calls.
CounterMetric<status_t> mProvideProvisionResponseCounter;
-
// Count of key status events broken out by status type.
- CounterMetric<::android::hardware::drm::V1_2::KeyStatusType>
- mKeyStatusChangeCounter;
+ CounterMetric<uint32_t> mKeyStatusChangeCounter;
// Count of events broken out by event type
- CounterMetric<::android::hardware::drm::V1_0::EventType> mEventCounter;
+ CounterMetric<uint32_t> mEventCounter;
// Count getPropertyByteArray calls to retrieve the device unique id.
CounterMetric<status_t> mGetDeviceUniqueIdCounter;
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index ec0b878..5679cfd 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -38,12 +38,18 @@
#include <mutex>
#include <string>
#include <vector>
+#include <aidl/android/hardware/drm/LogMessage.h>
+#include <aidl/android/hardware/drm/Status.h>
using namespace ::android::hardware::drm;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
+using ::aidl::android::hardware::drm::LogPriority;
+using ::aidl::android::hardware::drm::LogMessage;
+using StatusAidl = ::aidl::android::hardware::drm::Status;
+
namespace android {
struct ICrypto;
@@ -180,6 +186,136 @@
return toStatusT_1_4(err);
}
+inline status_t toStatusTAidl(int32_t serviceError) {
+ auto status = static_cast<StatusAidl>(serviceError);
+ switch (status) {
+ case StatusAidl::OK:
+ return OK;
+ case StatusAidl::BAD_VALUE:
+ return BAD_VALUE;
+ case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ case StatusAidl::ERROR_DRM_DECRYPT:
+ return ERROR_DRM_DECRYPT;
+ case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
+ return ERROR_DRM_DEVICE_REVOKED;
+ case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ case StatusAidl::ERROR_DRM_INVALID_STATE:
+ return ERROR_DRM_INVALID_STATE;
+ case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ case StatusAidl::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
+ return ERROR_DRM_NOT_PROVISIONED;
+ case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
+ return ERROR_DRM_RESOURCE_CONTENTION;
+ case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
+ return ERROR_DRM_SESSION_LOST_STATE;
+ case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
+
+ // New in S / drm@1.4:
+ case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+ return ERROR_DRM_ZERO_SUBSAMPLES;
+ case StatusAidl::CRYPTO_LIBRARY_ERROR:
+ return ERROR_DRM_CRYPTO_LIBRARY;
+ case StatusAidl::GENERAL_OEM_ERROR:
+ return ERROR_DRM_GENERIC_OEM;
+ case StatusAidl::GENERAL_PLUGIN_ERROR:
+ return ERROR_DRM_GENERIC_PLUGIN;
+ case StatusAidl::INIT_DATA_INVALID:
+ return ERROR_DRM_INIT_DATA;
+ case StatusAidl::KEY_NOT_LOADED:
+ return ERROR_DRM_KEY_NOT_LOADED;
+ case StatusAidl::LICENSE_PARSE_ERROR:
+ return ERROR_DRM_LICENSE_PARSE;
+ case StatusAidl::LICENSE_POLICY_ERROR:
+ return ERROR_DRM_LICENSE_POLICY;
+ case StatusAidl::LICENSE_RELEASE_ERROR:
+ return ERROR_DRM_LICENSE_RELEASE;
+ case StatusAidl::LICENSE_REQUEST_REJECTED:
+ return ERROR_DRM_LICENSE_REQUEST_REJECTED;
+ case StatusAidl::LICENSE_RESTORE_ERROR:
+ return ERROR_DRM_LICENSE_RESTORE;
+ case StatusAidl::LICENSE_STATE_ERROR:
+ return ERROR_DRM_LICENSE_STATE;
+ case StatusAidl::MALFORMED_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MALFORMED;
+ case StatusAidl::MEDIA_FRAMEWORK_ERROR:
+ return ERROR_DRM_MEDIA_FRAMEWORK;
+ case StatusAidl::MISSING_CERTIFICATE:
+ return ERROR_DRM_CERTIFICATE_MISSING;
+ case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
+ return ERROR_DRM_PROVISIONING_CERTIFICATE;
+ case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
+ return ERROR_DRM_PROVISIONING_CONFIG;
+ case StatusAidl::PROVISIONING_PARSE_ERROR:
+ return ERROR_DRM_PROVISIONING_PARSE;
+ case StatusAidl::PROVISIONING_REQUEST_REJECTED:
+ return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+ case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
+ return ERROR_DRM_PROVISIONING_RETRY;
+ case StatusAidl::SECURE_STOP_RELEASE_ERROR:
+ return ERROR_DRM_SECURE_STOP_RELEASE;
+ case StatusAidl::STORAGE_READ_FAILURE:
+ return ERROR_DRM_STORAGE_READ;
+ case StatusAidl::STORAGE_WRITE_FAILURE:
+ return ERROR_DRM_STORAGE_WRITE;
+
+ case StatusAidl::ERROR_DRM_UNKNOWN:
+ default:
+ return ERROR_DRM_UNKNOWN;
+ }
+ return ERROR_DRM_UNKNOWN;
+}
+
+template<typename T, typename U>
+status_t GetLogMessagesAidl(const std::shared_ptr<U> &obj, Vector<::V1_4::LogMessage> &logs) {
+ std::shared_ptr<T> plugin = obj;
+ if (obj == NULL) {
+ LOG2BW("%s obj is null", U::descriptor);
+ } else if (plugin == NULL) {
+ LOG2BW("Cannot cast %s obj to %s plugin", U::descriptor, T::descriptor);
+ }
+
+ std::vector<LogMessage> pluginLogsAidl;
+ if (plugin != NULL) {
+ if(!plugin->getLogMessages(&pluginLogsAidl).isOk()) {
+ LOG2BW("%s::getLogMessages remote call failed", T::descriptor);
+ }
+ }
+
+ std::vector<::V1_4::LogMessage> pluginLogs;
+ for (LogMessage log : pluginLogsAidl) {
+ ::V1_4::LogMessage logHidl;
+ logHidl.timeMs = log.timeMs;
+ // skip negative convert check as count of enum elements is 7
+ logHidl.priority = static_cast<::V1_4::LogPriority>((int32_t)log.priority);
+ logHidl.message = log.message;
+ pluginLogs.push_back(logHidl);
+ }
+
+ auto allLogs(gLogBuf.getLogs());
+ LOG2BD("framework logs size %zu; plugin logs size %zu",
+ allLogs.size(), pluginLogs.size());
+ std::copy(pluginLogs.begin(), pluginLogs.end(), std::back_inserter(allLogs));
+ std::sort(allLogs.begin(), allLogs.end(),
+ [](const ::V1_4::LogMessage &a, const ::V1_4::LogMessage &b) {
+ return a.timeMs < b.timeMs;
+ });
+
+ logs.appendVector(allLogs);
+ return OK;
+}
+
template<typename T, typename U>
status_t GetLogMessages(const sp<U> &obj, Vector<::V1_4::LogMessage> &logs) {
sp<T> plugin = T::castFrom(obj);
diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp
index f362d60..237a88b 100644
--- a/drm/libmediadrm/tests/DrmMetrics_test.cpp
+++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp
@@ -83,8 +83,8 @@
metrics.mProvideProvisionResponseCounter.Increment(OK);
metrics.mGetDeviceUniqueIdCounter.Increment(OK);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
- metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
+ metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
PersistableBundle bundle;
DrmMetricsConsumer consumer(&bundle);
@@ -151,16 +151,16 @@
metrics.mGetDeviceUniqueIdCounter.Increment(OK);
metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::EXPIRED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::OUTPUTNOTALLOWED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::STATUSPENDING);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::INTERNALERROR);
- metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
- metrics.mEventCounter.Increment(EventType::KEY_NEEDED);
- metrics.mEventCounter.Increment(EventType::KEY_EXPIRED);
- metrics.mEventCounter.Increment(EventType::VENDOR_DEFINED);
- metrics.mEventCounter.Increment(EventType::SESSION_RECLAIMED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::EXPIRED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::OUTPUTNOTALLOWED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::STATUSPENDING);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::INTERNALERROR);
+ metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_NEEDED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_EXPIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::VENDOR_DEFINED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::SESSION_RECLAIMED);
android::Vector<uint8_t> sessionId1;
sessionId1.push_back(1);
@@ -284,16 +284,16 @@
metrics.mGetDeviceUniqueIdCounter.Increment(OK);
metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::USABLE);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::EXPIRED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::OUTPUTNOTALLOWED);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::STATUSPENDING);
- metrics.mKeyStatusChangeCounter.Increment(KeyStatusType::INTERNALERROR);
- metrics.mEventCounter.Increment(EventType::PROVISION_REQUIRED);
- metrics.mEventCounter.Increment(EventType::KEY_NEEDED);
- metrics.mEventCounter.Increment(EventType::KEY_EXPIRED);
- metrics.mEventCounter.Increment(EventType::VENDOR_DEFINED);
- metrics.mEventCounter.Increment(EventType::SESSION_RECLAIMED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::EXPIRED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::OUTPUTNOTALLOWED);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::STATUSPENDING);
+ metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::INTERNALERROR);
+ metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_NEEDED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::KEY_EXPIRED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::VENDOR_DEFINED);
+ metrics.mEventCounter.Increment((uint32_t)EventType::SESSION_RECLAIMED);
std::string serializedMetrics;
ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index ac97e73..ac1a7e9 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -73,6 +73,7 @@
"libmedia",
"libmediadrm",
"libpowermanager",
+ "android.hardware.drm-V1-ndk",
],
static_libs: [
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 6c5e6cb..f50acae 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -145,6 +145,7 @@
"libgui",
"libui",
"libmediandk_utils",
+ "android.hardware.drm-V1-ndk",
],
export_header_lib_headers: ["jni_headers"],