Implement client code to use Drm and Crypto HALs
This change adds DrmHal & CryptoHal classes that connect to the Treble
HAL interfaces for drm. These classes mirror the existing Drm and
Crypto classes that connect to the DrmPlugin and CryptoPlugin
interfaces. Having both allows mediadrmserver to run in either mode
while the HAL is stabilized.
The shared memory interfaces between mediaserver's ACodecBufferChannel
and ICrypto had to be reworked to use the Treble HALs. Specifically,
the shared memory path for returning decrypted buffers in the
non-secure case had to become separate instead of piggy-backing on the
source shared memory buffer. A separate shared memory destination
buffer is now allocated on the buffer channel. An abstraction for a
decrypt destination buffer was also introduced to clarify ICrypto's
decrypt method.
Tests: Playback using Play Movies and ExoPlayer works on angler
with and without the treble hal enabled.
bug: 32815560
Change-Id: I5a3dc84f99902eb8cf8eabab9ad074d307744950
diff --git a/drm/libmediadrm/Android.mk b/drm/libmediadrm/Android.mk
index 3f0e663..7e77aac 100644
--- a/drm/libmediadrm/Android.mk
+++ b/drm/libmediadrm/Android.mk
@@ -7,14 +7,21 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- Crypto.cpp \
- Drm.cpp \
DrmSessionManager.cpp \
ICrypto.cpp \
IDrm.cpp \
IDrmClient.cpp \
IMediaDrmService.cpp \
SharedLibrary.cpp
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_SRC_FILES += \
+ DrmHal.cpp \
+ CryptoHal.cpp
+else
+LOCAL_SRC_FILES += \
+ Drm.cpp \
+ Crypto.cpp
+endif
LOCAL_SHARED_LIBRARIES := \
libbinder \
@@ -24,6 +31,13 @@
libmediautils \
libstagefright_foundation \
libutils
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_SHARED_LIBRARIES += \
+ android.hidl.base@1.0 \
+ android.hardware.drm@1.0 \
+ libhidlbase \
+ libhidlmemory
+endif
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
diff --git a/drm/libmediadrm/Crypto.cpp b/drm/libmediadrm/Crypto.cpp
index 79633cb..d93dad6 100644
--- a/drm/libmediadrm/Crypto.cpp
+++ b/drm/libmediadrm/Crypto.cpp
@@ -233,16 +233,12 @@
return mPlugin->requiresSecureDecoderComponent(mime);
}
-ssize_t Crypto::decrypt(
- DestinationType dstType,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &sharedBuffer, size_t offset,
+ssize_t Crypto::decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- void *dstPtr,
- AString *errorDetailMsg) {
+ const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -253,12 +249,21 @@
return -EINVAL;
}
- const void *srcPtr = static_cast<uint8_t *>(sharedBuffer->pointer()) + offset;
+ const void *srcPtr = static_cast<uint8_t *>(source->pointer()) + offset;
- return mPlugin->decrypt(
- dstType != kDestinationTypeVmPointer,
- key, iv, mode, pattern, srcPtr, subSamples, numSubSamples, dstPtr,
- errorDetailMsg);
+ void *destPtr;
+ bool secure = false;
+ if (destination.mType == kDestinationTypeNativeHandle) {
+ destPtr = static_cast<void *>(destination.mHandle);
+ secure = true;
+ } else {
+ destPtr = destination.mSharedMemory->pointer();
+ }
+
+ ssize_t result = mPlugin->decrypt(secure, key, iv, mode, pattern, srcPtr, subSamples,
+ numSubSamples, destPtr, errorDetailMsg);
+
+ return result;
}
void Crypto::notifyResolution(uint32_t width, uint32_t height) {
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
new file mode 100644
index 0000000..f1f3b01
--- /dev/null
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -0,0 +1,328 @@
+/*
+ * 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 "CryptoHal"
+#include <utils/Log.h>
+#include <dirent.h>
+#include <dlfcn.h>
+
+#include <android/hardware/drm/1.0/types.h>
+
+#include <binder/IMemory.h>
+#include <cutils/native_handle.h>
+#include <media/CryptoHal.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>
+
+using ::android::hardware::drm::V1_0::BufferType;
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SharedBuffer;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+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::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+
+namespace android {
+
+static status_t toStatusT(Status status) {
+ switch (status) {
+ case Status::OK:
+ return OK;
+ case Status::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ case Status::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ case Status::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+ case Status::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
+ case Status::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ default:
+ return UNKNOWN_ERROR;
+ }
+}
+
+
+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 ::SharedBuffer toSharedBuffer(const sp<IMemory>& sharedBuffer) {
+ ssize_t offset;
+ size_t size;
+ sharedBuffer->getMemory(&offset, &size);
+
+ ::SharedBuffer buffer;
+ buffer.offset = offset >= 0 ? offset : 0;
+ buffer.size = size;
+ return buffer;
+}
+
+static String8 toString8(hidl_string hString) {
+ return String8(hString.c_str());
+}
+
+
+CryptoHal::CryptoHal()
+ : mFactory(makeCryptoFactory()),
+ mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT),
+ mHeapBase(NULL) {
+}
+
+CryptoHal::~CryptoHal() {
+}
+
+
+sp<ICryptoFactory> CryptoHal::makeCryptoFactory() {
+ sp<ICryptoFactory> factory = ICryptoFactory::getService("crypto");
+ if (factory == NULL) {
+ ALOGE("Failed to make crypto factory");
+ }
+ return factory;
+}
+
+sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const uint8_t uuid[16],
+ const void *initData, size_t initDataSize) {
+ if (mFactory == NULL){
+ return NULL;
+ }
+
+ sp<ICryptoPlugin> plugin;
+ Return<void> hResult = mFactory->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;
+ }
+ );
+ return plugin;
+}
+
+
+status_t CryptoHal::initCheck() const {
+ return mInitCheck;
+}
+
+
+bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+ if (mFactory != NULL) {
+ return mFactory->isCryptoSchemeSupported(uuid);
+ }
+ return false;
+}
+
+status_t CryptoHal::createPlugin(
+ const uint8_t uuid[16], const void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ mPlugin = makeCryptoPlugin(uuid, data, size);
+
+ if (mPlugin == NULL) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ } else {
+ mInitCheck = OK;
+ }
+
+ return mInitCheck;
+}
+
+status_t CryptoHal::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ mPlugin.clear();
+ return OK;
+}
+
+bool CryptoHal::requiresSecureDecoderComponent(const char *mime) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ return mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
+}
+
+
+/**
+ * If the heap base isn't set, get the heap base from the IMemory
+ * 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.
+ */
+status_t CryptoHal::setHeapBase(const sp<IMemory>& sharedBuffer) {
+ sp<IMemoryHeap> heap = sharedBuffer->getMemory(NULL, NULL);
+ if (mHeapBase != heap->getBase()) {
+ int fd = heap->getHeapID();
+ native_handle_t* nativeHandle = native_handle_create(1, 0);
+ nativeHandle->data[0] = fd;
+ auto hidlHandle = hidl_handle(nativeHandle);
+ auto hidlMemory = hidl_memory("ashmem", hidlHandle, heap->getSize());
+ mHeapBase = heap->getBase();
+ Return<void> hResult = mPlugin->setSharedBufferBase(hidlMemory);
+ if (!hResult.isOk()) {
+ return DEAD_OBJECT;
+ }
+ }
+ return OK;
+}
+
+ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ // Establish the base of the shared memory heap
+ setHeapBase(source);
+
+ 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;
+ ::DestinationBuffer hDestination;
+ if (destination.mType == kDestinationTypeSharedMemory) {
+ hDestination.type = BufferType::SHARED_MEMORY;
+ hDestination.nonsecureMemory = toSharedBuffer(destination.mSharedMemory);
+ secure = false;
+ } else {
+ hDestination.type = BufferType::NATIVE_HANDLE;
+ hDestination.secureMemory = hidl_handle(destination.mHandle);
+ secure = true;
+ }
+
+
+ status_t err = UNKNOWN_ERROR;
+ uint32_t bytesWritten = 0;
+
+ Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode,
+ hPattern, hSubSamples, toSharedBuffer(source), offset, hDestination,
+ [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+ if (status == Status::OK) {
+ bytesWritten = hBytesWritten;
+ *errorDetailMsg = toString8(hDetailedError);
+ }
+ err = toStatusT(status);
+ }
+ );
+
+ if (!hResult.isOk()) {
+ err = DEAD_OBJECT;
+ }
+
+ if (err == OK) {
+ return bytesWritten;
+ }
+ return err;
+}
+
+void CryptoHal::notifyResolution(uint32_t width, uint32_t height) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ mPlugin->notifyResolution(width, height);
+}
+
+status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t> &sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ return toStatusT(mPlugin->setMediaDrmSession(toHidlVec(sessionId)));
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
new file mode 100644
index 0000000..304cdaf
--- /dev/null
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -0,0 +1,950 @@
+/*
+ * 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 "DrmHal"
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <dirent.h>
+#include <dlfcn.h>
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/types.h>
+
+#include <media/DrmHal.h>
+#include <media/DrmSessionClientInterface.h>
+#include <media/DrmSessionManager.h>
+#include <media/drm/DrmAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaErrors.h>
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::KeyedVector;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyStatusType;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::drm::V1_0::Status;
+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::sp;
+
+namespace android {
+
+static inline int getCallingPid() {
+ return IPCThreadState::self()->getCallingPid();
+}
+
+static bool checkPermission(const char* permissionString) {
+ if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+ bool ok = checkCallingPermission(String16(permissionString));
+ if (!ok) ALOGE("Request requires %s", permissionString);
+ return ok;
+}
+
+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 ::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 status_t toStatusT(Status status) {
+ switch (status) {
+ case Status::OK:
+ return OK;
+ break;
+ case Status::ERROR_DRM_NO_LICENSE:
+ return ERROR_DRM_NO_LICENSE;
+ break;
+ case Status::ERROR_DRM_LICENSE_EXPIRED:
+ return ERROR_DRM_LICENSE_EXPIRED;
+ break;
+ case Status::ERROR_DRM_SESSION_NOT_OPENED:
+ return ERROR_DRM_SESSION_NOT_OPENED;
+ break;
+ case Status::ERROR_DRM_CANNOT_HANDLE:
+ return ERROR_DRM_CANNOT_HANDLE;
+ break;
+ case Status::ERROR_DRM_INVALID_STATE:
+ return ERROR_DRM_TAMPER_DETECTED;
+ break;
+ case Status::BAD_VALUE:
+ return BAD_VALUE;
+ break;
+ case Status::ERROR_DRM_NOT_PROVISIONED:
+ return ERROR_DRM_NOT_PROVISIONED;
+ break;
+ case Status::ERROR_DRM_RESOURCE_BUSY:
+ return ERROR_DRM_RESOURCE_BUSY;
+ break;
+ case Status::ERROR_DRM_DEVICE_REVOKED:
+ return ERROR_DRM_DEVICE_REVOKED;
+ break;
+ case Status::ERROR_DRM_UNKNOWN:
+ default:
+ return ERROR_DRM_UNKNOWN;
+ break;
+ }
+}
+
+
+Mutex DrmHal::mLock;
+
+struct DrmSessionClient : public DrmSessionClientInterface {
+ explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
+
+ virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
+ sp<DrmHal> drm = mDrm.promote();
+ if (drm == NULL) {
+ return true;
+ }
+ status_t err = drm->closeSession(sessionId);
+ if (err != OK) {
+ return false;
+ }
+ drm->sendEvent(EventType::SESSION_RECLAIMED,
+ toHidlVec(sessionId), hidl_vec<uint8_t>());
+ return true;
+ }
+
+protected:
+ virtual ~DrmSessionClient() {}
+
+private:
+ wp<DrmHal> mDrm;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
+};
+
+DrmHal::DrmHal()
+ : mDrmSessionClient(new DrmSessionClient(this)),
+ mFactory(makeDrmFactory()),
+ mInitCheck((mFactory == NULL) ? ERROR_UNSUPPORTED : NO_INIT) {
+}
+
+DrmHal::~DrmHal() {
+ DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
+}
+
+sp<IDrmFactory> DrmHal::makeDrmFactory() {
+ sp<IDrmFactory> factory = IDrmFactory::getService("drm");
+ if (factory == NULL) {
+ ALOGE("Failed to make drm factory");
+ }
+ return factory;
+}
+
+sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16]) {
+ if (mFactory == NULL){
+ return NULL;
+ }
+
+ sp<IDrmPlugin> plugin;
+ Return<void> hResult = mFactory->createPlugin(uuid,
+ [&](Status status, const sp<IDrmPlugin>& hPlugin) {
+ if (status != Status::OK) {
+ ALOGD("Failed to make drm plugin");
+ return;
+ }
+ plugin = hPlugin;
+ }
+ );
+ return plugin;
+}
+
+status_t DrmHal::initCheck() const {
+ return mInitCheck;
+}
+
+status_t DrmHal::setListener(const sp<IDrmClient>& listener)
+{
+ Mutex::Autolock lock(mEventLock);
+ if (mListener != NULL){
+ IInterface::asBinder(mListener)->unlinkToDeath(this);
+ }
+ if (listener != NULL) {
+ IInterface::asBinder(listener)->linkToDeath(this);
+ }
+ mListener = listener;
+ return NO_ERROR;
+}
+
+Return<void> DrmHal::sendEvent(EventType hEventType,
+ const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+ writeByteArray(obj, data);
+
+ 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;
+ default:
+ return Void();
+ }
+ listener->notify(eventType, 0, &obj);
+ }
+ 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) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+ obj.writeInt64(expiryTimeInMS);
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+ }
+ return Void();
+}
+
+Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+
+ size_t nKeys = keyStatusList.size();
+ obj.writeInt32(nKeys);
+ for (size_t i = 0; i < nKeys; ++i) {
+ const KeyStatus &keyStatus = keyStatusList[i];
+ writeByteArray(obj, keyStatus.keyId);
+ 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::INTERNALERROR:
+ default:
+ type = DrmPlugin::kKeyStatusType_InternalError;
+ break;
+ }
+ obj.writeInt32(type);
+ }
+ obj.writeInt32(hasNewUsableKey);
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+ }
+ return Void();
+}
+
+bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
+ Mutex::Autolock autoLock(mLock);
+ bool result = false;
+
+ if (mFactory != NULL && mFactory->isCryptoSchemeSupported(uuid)) {
+ if (mimeType != "") {
+ result = mFactory->isContentTypeSupported(mimeType.string());
+ }
+ }
+ return result;
+}
+
+status_t DrmHal::createPlugin(const uint8_t uuid[16]) {
+ Mutex::Autolock autoLock(mLock);
+
+ mPlugin = makeDrmPlugin(uuid);
+
+ if (mPlugin == NULL) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ } else {
+ mInitCheck = OK;
+ mPlugin->setListener(this);
+ }
+
+ return mInitCheck;
+}
+
+status_t DrmHal::destroyPlugin() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ setListener(NULL);
+ mPlugin.clear();
+
+ return OK;
+}
+
+status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ bool retry = true;
+ do {
+ hidl_vec<uint8_t> hSessionId;
+
+ Return<void> hResult = mPlugin->openSession(
+ [&](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(getCallingPid());
+ mLock.lock();
+ } else {
+ retry = false;
+ }
+ } while (retry);
+
+ if (err == OK) {
+ DrmSessionManager::Instance()->addSession(getCallingPid(),
+ mDrmSessionClient, sessionId);
+ }
+ return err;
+}
+
+status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ Status status = mPlugin->closeSession(toHidlVec(sessionId));
+ if (status == Status::OK) {
+ DrmSessionManager::Instance()->removeSession(sessionId);
+ }
+ return toStatusT(status);
+}
+
+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);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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 {
+ return BAD_VALUE;
+ }
+
+ ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> 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);
+
+ switch (hKeyRequestType) {
+ case KeyRequestType::INITIAL:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case KeyRequestType::RENEWAL:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case KeyRequestType::RELEASE:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Release;
+ break;
+ default:
+ *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+ err = toStatusT(status);
+ }
+ });
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
+}
+
+status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keySetId) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
+ toHidlVec(keySetId)));
+}
+
+status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
+ KeyedVector<String8, String8> &infoMap) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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::getProvisionRequest(String8 const &certType,
+ String8 const &certAuthority, Vector<uint8_t> &request,
+ String8 &defaultUrl) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ status_t err = UNKNOWN_ERROR;
+
+ Return<void> 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);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
+ Vector<uint8_t> &certificate,
+ Vector<uint8_t> &wrappedKey) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::getSecureStops(List<Vector<uint8_t> > &secureStops) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
+}
+
+status_t DrmHal::releaseAllSecureStops() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ return toStatusT(mPlugin->releaseAllSecureStops());
+}
+
+status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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 {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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);
+ }
+ );
+
+ return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ Status status = mPlugin->setPropertyString(toHidlString(name),
+ toHidlString(value));
+ return toStatusT(status);
+}
+
+status_t DrmHal::setPropertyByteArray(String8 const &name,
+ Vector<uint8_t> const &value ) const {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ Status status = mPlugin->setPropertyByteArray(toHidlString(name),
+ toHidlVec(value));
+ return toStatusT(status);
+}
+
+
+status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
+ toHidlString(algorithm));
+ return toStatusT(status);
+}
+
+status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
+ String8 const &algorithm) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ DrmSessionManager::Instance()->useSession(sessionId);
+
+ Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
+ toHidlString(algorithm));
+ return toStatusT(status);
+}
+
+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);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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::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);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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::sign(Vector<uint8_t> const &sessionId,
+ Vector<uint8_t> const &keyId,
+ Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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::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);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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::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);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
+ return -EPERM;
+ }
+
+ 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;
+}
+
+void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
+{
+ mEventLock.lock();
+ mListener.clear();
+ mEventLock.unlock();
+
+ Mutex::Autolock autoLock(mLock);
+ mPlugin.clear();
+}
+
+void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
+{
+ if (vec.size()) {
+ obj.writeInt32(vec.size());
+ obj.write(vec.data(), vec.size());
+ } else {
+ obj.writeInt32(0);
+ }
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
index 8ba80c6..10e6bc3 100644
--- a/drm/libmediadrm/ICrypto.cpp
+++ b/drm/libmediadrm/ICrypto.cpp
@@ -94,18 +94,13 @@
return reply.readInt32() != 0;
}
- virtual ssize_t decrypt(
- DestinationType dstType,
- const uint8_t key[16],
- const uint8_t iv[16],
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &sharedBuffer, size_t offset,
+ const sp<IMemory> &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- void *dstPtr,
- AString *errorDetailMsg) {
+ const DestinationBuffer &destination, AString *errorDetailMsg) {
Parcel data, reply;
data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeInt32((int32_t)dstType);
data.writeInt32(mode);
data.writeInt32(pattern.mEncryptBlocks);
data.writeInt32(pattern.mSkipBlocks);
@@ -130,18 +125,23 @@
}
data.writeInt32(totalSize);
- data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
+ data.writeStrongBinder(IInterface::asBinder(source));
data.writeInt32(offset);
data.writeInt32(numSubSamples);
data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
- if (dstType == kDestinationTypeNativeHandle) {
- data.writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
- } else if (dstType == kDestinationTypeOpaqueHandle) {
- data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
+ data.writeInt32((int32_t)destination.mType);
+ if (destination.mType == kDestinationTypeNativeHandle) {
+ if (destination.mHandle == NULL) {
+ return BAD_VALUE;
+ }
+ data.writeNativeHandle(destination.mHandle);
} else {
- dstType = kDestinationTypeVmPointer;
+ if (destination.mSharedMemory == NULL) {
+ return BAD_VALUE;
+ }
+ data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
}
remote()->transact(DECRYPT, data, &reply);
@@ -150,10 +150,6 @@
if (isCryptoError(result)) {
errorDetailMsg->setTo(reply.readCString());
- } else if (dstType == kDestinationTypeVmPointer) {
- // For the non-secure case, copy the decrypted
- // data from shared memory to its final destination
- memcpy(dstPtr, sharedBuffer->pointer(), result);
}
return result;
@@ -280,7 +276,6 @@
{
CHECK_INTERFACE(ICrypto, data, reply);
- DestinationType dstType = (DestinationType)data.readInt32();
CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
CryptoPlugin::Pattern pattern;
pattern.mEncryptBlocks = data.readInt32();
@@ -293,9 +288,9 @@
data.read(iv, sizeof(iv));
size_t totalSize = data.readInt32();
- sp<IMemory> sharedBuffer =
+ sp<IMemory> source =
interface_cast<IMemory>(data.readStrongBinder());
- if (sharedBuffer == NULL) {
+ if (source == NULL) {
reply->writeInt32(BAD_VALUE);
return OK;
}
@@ -308,23 +303,26 @@
}
CryptoPlugin::SubSample *subSamples =
- new CryptoPlugin::SubSample[numSubSamples];
+ new CryptoPlugin::SubSample[numSubSamples];
- data.read(
- subSamples,
+ data.read(subSamples,
sizeof(CryptoPlugin::SubSample) * numSubSamples);
- native_handle_t *nativeHandle = NULL;
- void *secureBufferId = NULL, *dstPtr;
- if (dstType == kDestinationTypeNativeHandle) {
- nativeHandle = data.readNativeHandle();
- dstPtr = static_cast<void *>(nativeHandle);
- } else if (dstType == kDestinationTypeOpaqueHandle) {
- secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
- dstPtr = secureBufferId;
- } else {
- dstType = kDestinationTypeVmPointer;
- dstPtr = malloc(totalSize);
+ DestinationBuffer destination;
+ destination.mType = (DestinationType)data.readInt32();
+ if (destination.mType == kDestinationTypeNativeHandle) {
+ destination.mHandle = data.readNativeHandle();
+ if (destination.mHandle == NULL) {
+ reply->writeInt32(BAD_VALUE);
+ return OK;
+ }
+ } else if (destination.mType == kDestinationTypeSharedMemory) {
+ destination.mSharedMemory =
+ interface_cast<IMemory>(data.readStrongBinder());
+ if (destination.mSharedMemory == NULL) {
+ reply->writeInt32(BAD_VALUE);
+ return OK;
+ }
}
AString errorDetailMsg;
@@ -348,20 +346,13 @@
if (overflow || sumSubsampleSizes != totalSize) {
result = -EINVAL;
- } else if (totalSize > sharedBuffer->size()) {
+ } else if (totalSize > source->size()) {
result = -EINVAL;
- } else if ((size_t)offset > sharedBuffer->size() - totalSize) {
+ } else if ((size_t)offset > source->size() - totalSize) {
result = -EINVAL;
} else {
- result = decrypt(
- dstType,
- key,
- iv,
- mode, pattern,
- sharedBuffer, offset,
- subSamples, numSubSamples,
- dstPtr,
- &errorDetailMsg);
+ result = decrypt(key, iv, mode, pattern, source, offset,
+ subSamples, numSubSamples, destination, &errorDetailMsg);
}
reply->writeInt32(result);
@@ -370,23 +361,12 @@
reply->writeCString(errorDetailMsg.c_str());
}
- if (dstType == kDestinationTypeVmPointer) {
- if (result >= 0) {
- CHECK_LE(result, static_cast<ssize_t>(totalSize));
- // For the non-secure case, pass the decrypted
- // data back via the shared buffer rather than
- // copying it separately over binder to avoid
- // binder's 1MB limit.
- memcpy(sharedBuffer->pointer(), dstPtr, result);
- }
- free(dstPtr);
- dstPtr = NULL;
- } else if (dstType == kDestinationTypeNativeHandle) {
+ if (destination.mType == kDestinationTypeNativeHandle) {
int err;
- if ((err = native_handle_close(nativeHandle)) < 0) {
+ if ((err = native_handle_close(destination.mHandle)) < 0) {
ALOGW("secure buffer native_handle_close failed: %d", err);
}
- if ((err = native_handle_delete(nativeHandle)) < 0) {
+ if ((err = native_handle_delete(destination.mHandle)) < 0) {
ALOGW("secure buffer native_handle_delete failed: %d", err);
}
}
diff --git a/include/media/Crypto.h b/include/media/Crypto.h
index 7d181d3..ce08f98 100644
--- a/include/media/Crypto.h
+++ b/include/media/Crypto.h
@@ -49,16 +49,11 @@
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
- virtual ssize_t decrypt(
- DestinationType dstType,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &sharedBuffer, size_t offset,
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- void *dstPtr,
- AString *errorDetailMsg);
+ const DestinationBuffer &destination, AString *errorDetailMsg);
private:
mutable Mutex mLock;
diff --git a/include/media/CryptoHal.h b/include/media/CryptoHal.h
new file mode 100644
index 0000000..1ace957
--- /dev/null
+++ b/include/media/CryptoHal.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#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 <media/ICrypto.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+#include "SharedLibrary.h"
+
+namespace android {
+
+struct CryptoHal : public BnCrypto {
+ 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 sp<IMemory> &source, size_t offset,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
+ const ICrypto::DestinationBuffer &destination,
+ AString *errorDetailMsg);
+
+private:
+ mutable Mutex mLock;
+
+ sp<SharedLibrary> mLibrary;
+ sp<::android::hardware::drm::V1_0::ICryptoFactory> mFactory;
+ sp<::android::hardware::drm::V1_0::ICryptoPlugin> 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;
+
+ void *mHeapBase;
+
+ sp<::android::hardware::drm::V1_0::ICryptoFactory>
+ makeCryptoFactory();
+ sp<::android::hardware::drm::V1_0::ICryptoPlugin>
+ makeCryptoPlugin(const uint8_t uuid[16], const void *initData,
+ size_t size);
+
+ status_t setHeapBase(const sp<IMemory> &sharedBuffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
+};
+
+} // namespace android
+
+#endif // CRYPTO_HAL_H_
diff --git a/include/media/DrmHal.h b/include/media/DrmHal.h
new file mode 100644
index 0000000..aaea2c9
--- /dev/null
+++ b/include/media/DrmHal.h
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+#ifndef DRM_HAL_H_
+
+#define DRM_HAL_H_
+
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+
+#include <media/IDrm.h>
+#include <media/IDrmClient.h>
+#include <utils/threads.h>
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+namespace android {
+
+struct DrmSessionClientInterface;
+
+struct DrmHal : public BnDrm,
+ public IBinder::DeathRecipient,
+ public IDrmPluginListener {
+ DrmHal();
+ virtual ~DrmHal();
+
+ virtual status_t initCheck() const;
+
+ virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
+
+ virtual status_t createPlugin(const uint8_t uuid[16]);
+
+ virtual status_t destroyPlugin();
+
+ virtual status_t openSession(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 &defaulUrl);
+
+ 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 getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+
+ virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
+ virtual status_t releaseAllSecureStops();
+
+ 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 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);
+
+ // 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>& keyStatusList, bool hasNewUsableKey);
+
+ virtual void binderDied(const wp<IBinder> &the_late_who);
+
+private:
+ static Mutex mLock;
+
+ sp<DrmSessionClientInterface> mDrmSessionClient;
+
+ sp<IDrmClient> mListener;
+ mutable Mutex mEventLock;
+ mutable Mutex mNotifyLock;
+
+ sp<IDrmFactory> mFactory;
+ sp<IDrmPlugin> 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;
+
+ sp<IDrmFactory> makeDrmFactory();
+ sp<IDrmPlugin> makeDrmPlugin(const uint8_t uuid[16]);
+
+ void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmHal);
+};
+
+} // namespace android
+
+#endif // DRM_HAL_H_
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
index a4bfaf8..8990f4b 100644
--- a/include/media/ICrypto.h
+++ b/include/media/ICrypto.h
@@ -15,8 +15,9 @@
*/
#include <binder/IInterface.h>
-#include <media/stagefright/foundation/ABase.h>
+#include <cutils/native_handle.h>
#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/ABase.h>
#ifndef ANDROID_ICRYPTO_H_
@@ -47,21 +48,21 @@
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
enum DestinationType {
- kDestinationTypeVmPointer, // non-secure
- kDestinationTypeOpaqueHandle, // secure
+ kDestinationTypeSharedMemory, // non-secure
kDestinationTypeNativeHandle // secure
};
- virtual ssize_t decrypt(
- DestinationType dstType,
- const uint8_t key[16],
- const uint8_t iv[16],
- CryptoPlugin::Mode mode,
- const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &sharedBuffer, size_t offset,
+ struct DestinationBuffer {
+ DestinationType mType;
+ native_handle_t *mHandle;
+ sp<IMemory> mSharedMemory;
+ };
+
+ virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
+ CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
+ const sp<IMemory> &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- void *dstPtr,
- AString *errorDetailMsg) = 0;
+ const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
private:
DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
diff --git a/include/media/PluginLoader.h b/include/media/PluginLoader.h
index 360af2d..a626e16 100644
--- a/include/media/PluginLoader.h
+++ b/include/media/PluginLoader.h
@@ -60,7 +60,10 @@
}
}
- T *getFactory(size_t i) const {return factories[i];}
+ T *getFactory(size_t i) const {
+ return factories[i];
+ }
+
size_t factoryCount() const {return factories.size();}
private:
@@ -74,12 +77,11 @@
CreateFactoryFunc createFactoryFunc =
(CreateFactoryFunc)library->lookup(entry);
if (createFactoryFunc) {
+ ALOGV("Found plugin factory entry %s in %s", entry, path);
libraries.push(library);
- return createFactoryFunc();
- } else {
- ALOGE("Failed to create plugin factory from %s at entry %s: %s",
- path, entry, library->lastError());
- }
+ T* result = createFactoryFunc();
+ return result;
+ }
}
return NULL;
}
diff --git a/media/libmediaplayerservice/tests/Android.mk b/media/libmediaplayerservice/tests/Android.mk
index c0b3265..dc761ec 100644
--- a/media/libmediaplayerservice/tests/Android.mk
+++ b/media/libmediaplayerservice/tests/Android.mk
@@ -14,6 +14,8 @@
libmediaplayerservice \
libmediadrm \
libutils \
+ android.hidl.base@1.0 \
+ android.hardware.drm@1.0 \
LOCAL_C_INCLUDES := \
frameworks/av/include \
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 1db7ab0..296394b 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -88,14 +88,9 @@
}
status_t ACodecBufferChannel::queueSecureInputBuffer(
- const sp<MediaCodecBuffer> &buffer,
- bool secure,
- const uint8_t *key,
- const uint8_t *iv,
- CryptoPlugin::Mode mode,
- CryptoPlugin::Pattern pattern,
- const CryptoPlugin::SubSample *subSamples,
- size_t numSubSamples,
+ const sp<MediaCodecBuffer> &buffer, bool secure, const uint8_t *key,
+ const uint8_t *iv, CryptoPlugin::Mode mode, CryptoPlugin::Pattern pattern,
+ const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
AString *errorDetailMsg) {
if (mCrypto == nullptr) {
return -ENOSYS;
@@ -107,35 +102,32 @@
return -ENOENT;
}
- void *dst_pointer = nullptr;
- ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
-
+ ICrypto::DestinationBuffer destination;
if (secure) {
- sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(it->mCodecBuffer.get());
- dst_pointer = secureData->getDestinationPointer();
- dst_type = secureData->getDestinationType();
+ sp<SecureBuffer> secureData =
+ static_cast<SecureBuffer *>(it->mCodecBuffer.get());
+ destination.mType = secureData->getDestinationType();
+ if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
+ return BAD_VALUE;
+ }
+ destination.mHandle =
+ static_cast<native_handle_t *>(secureData->getDestinationPointer());
} else {
- dst_pointer = it->mCodecBuffer->base();
- dst_type = ICrypto::kDestinationTypeVmPointer;
+ destination.mType = ICrypto::kDestinationTypeSharedMemory;
+ destination.mSharedMemory = mDecryptDestination;
}
-
- ssize_t result = mCrypto->decrypt(
- dst_type,
- key,
- iv,
- mode,
- pattern,
- it->mSharedEncryptedBuffer,
- it->mClientBuffer->offset(),
- subSamples,
- numSubSamples,
- dst_pointer,
- errorDetailMsg);
+ ssize_t result = mCrypto->decrypt(key, iv, mode, pattern,
+ it->mSharedEncryptedBuffer, it->mClientBuffer->offset(),
+ subSamples, numSubSamples, destination, errorDetailMsg);
if (result < 0) {
return result;
}
+ if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+ memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
+ }
+
it->mCodecBuffer->setRange(0, result);
// Copy metadata from client to codec buffer.
@@ -228,7 +220,14 @@
(size_t sum, const BufferAndId& elem) {
return sum + align(elem.mBuffer->capacity(), alignment);
});
- mDealer = new MemoryDealer(totalSize, "ACodecBufferChannel");
+ size_t maxSize = std::accumulate(
+ array.begin(), array.end(), 0u,
+ [alignment = MemoryDealer::getAllocationAlignment()]
+ (size_t max, const BufferAndId& elem) {
+ return std::max(max, align(elem.mBuffer->capacity(), alignment));
+ });
+ mDealer = new MemoryDealer(totalSize + maxSize, "ACodecBufferChannel");
+ mDecryptDestination = mDealer->allocate(maxSize);
}
std::vector<const BufferInfo> inputBuffers;
for (const BufferAndId &elem : array) {
diff --git a/media/libstagefright/BufferImpl.cpp b/media/libstagefright/BufferImpl.cpp
index 37a40ec..40eb942 100644
--- a/media/libstagefright/BufferImpl.cpp
+++ b/media/libstagefright/BufferImpl.cpp
@@ -51,8 +51,7 @@
}
ICrypto::DestinationType SecureBuffer::getDestinationType() {
- return mHandle == nullptr ? ICrypto::kDestinationTypeOpaqueHandle
- : ICrypto::kDestinationTypeNativeHandle;
+ return ICrypto::kDestinationTypeNativeHandle;
}
} // namespace android
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index d52ce53..ce9bd3c 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -115,6 +115,7 @@
const sp<AMessage> mOutputBufferDrained;
sp<MemoryDealer> mDealer;
+ sp<IMemory> mDecryptDestination;
// These should only be accessed via std::atomic_* functions.
//
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 73109e1..f667068 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -16,7 +16,6 @@
include $(CLEAR_VARS)
-
LOCAL_SRC_FILES:= \
MediaDrmService.cpp \
main_mediadrmserver.cpp
@@ -26,8 +25,19 @@
liblog \
libmediadrm \
libutils \
+ libandroidfw
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_SHARED_LIBRARIES += \
+ libhidlbase \
+ libhidlmemory \
+ android.hidl.base@1.0 \
+ android.hardware.drm@1.0
+endif
LOCAL_CFLAGS += -Wall -Wextra -Werror
+ifeq ($(ENABLE_TREBLE_DRM), true)
+LOCAL_CFLAGS += -DENABLE_TREBLE_DRM=1
+endif
LOCAL_MODULE:= mediadrmserver
LOCAL_32_BIT_ONLY := true
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
index 331c568..c709b5e 100644
--- a/services/mediadrm/MediaDrmService.cpp
+++ b/services/mediadrm/MediaDrmService.cpp
@@ -21,11 +21,16 @@
#define LOG_TAG "MediaDrmService"
#include "MediaDrmService.h"
-
#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#ifdef ENABLE_TREBLE_DRM
+#include <media/CryptoHal.h>
+#include <media/DrmHal.h>
+#else
#include <media/Crypto.h>
#include <media/Drm.h>
-#include <utils/Log.h>
+#endif
namespace android {
@@ -35,11 +40,19 @@
}
sp<ICrypto> MediaDrmService::makeCrypto() {
+#ifdef ENABLE_TREBLE_DRM
+ return new CryptoHal;
+#else
return new Crypto;
+#endif
}
sp<IDrm> MediaDrmService::makeDrm() {
+#ifdef ENABLE_TREBLE_DRM
+ return new DrmHal;
+#else
return new Drm;
+#endif
}
} // namespace android