summaryrefslogtreecommitdiffstats
path: root/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drm')
-rw-r--r--drm/OWNERS1
-rw-r--r--drm/libmediadrm/Android.bp19
-rw-r--r--drm/libmediadrm/CasImpl.cpp224
-rw-r--r--drm/libmediadrm/DescramblerImpl.cpp154
-rw-r--r--drm/libmediadrm/DrmHal.cpp53
-rw-r--r--drm/libmediadrm/MediaCasDefs.cpp184
-rw-r--r--drm/libmediadrm/PluginMetricsReporting.cpp134
-rw-r--r--drm/libmediadrm/aidl/android/media/ICas.aidl33
-rw-r--r--drm/libmediadrm/aidl/android/media/ICasListener.aidl22
-rw-r--r--drm/libmediadrm/aidl/android/media/IDescrambler.aidl27
-rw-r--r--drm/libmediadrm/aidl/android/media/IMediaCasService.aidl32
-rw-r--r--drm/libmediadrm/aidl/android/media/MediaCas.aidl23
-rw-r--r--drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl20
-rw-r--r--drm/libmediadrm/protos/plugin_metrics.proto50
-rw-r--r--drm/mediacas/plugins/clearkey/Android.mk6
-rw-r--r--drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp16
-rw-r--r--drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp10
-rw-r--r--drm/mediacas/plugins/clearkey/ecm_generator.h2
-rw-r--r--drm/mediacas/plugins/clearkey/tests/Android.mk3
-rw-r--r--drm/mediacas/plugins/mock/Android.mk2
-rw-r--r--drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp11
-rw-r--r--drm/mediadrm/plugins/clearkey/DrmPlugin.cpp44
-rw-r--r--drm/mediadrm/plugins/clearkey/DrmPlugin.h17
-rw-r--r--drm/mediadrm/plugins/clearkey/InitDataParser.cpp2
-rw-r--r--drm/mediadrm/plugins/clearkey/tests/Android.bp1
-rw-r--r--drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp3
-rw-r--r--drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp10
-rw-r--r--drm/mediadrm/plugins/mock/Android.bp2
28 files changed, 335 insertions, 770 deletions
diff --git a/drm/OWNERS b/drm/OWNERS
new file mode 100644
index 0000000000..e788754d4e
--- /dev/null
+++ b/drm/OWNERS
@@ -0,0 +1 @@
+jtinker@google.com
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 66f5fc24ce..f90656434d 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -5,36 +5,31 @@
cc_library_shared {
name: "libmediadrm",
- aidl: {
- local_include_dirs: ["aidl"],
- export_aidl_headers: true,
- },
srcs: [
- "aidl/android/media/ICas.aidl",
- "aidl/android/media/ICasListener.aidl",
- "aidl/android/media/IDescrambler.aidl",
- "aidl/android/media/IMediaCasService.aidl",
-
- "CasImpl.cpp",
- "DescramblerImpl.cpp",
"DrmPluginPath.cpp",
"DrmSessionManager.cpp",
"ICrypto.cpp",
"IDrm.cpp",
"IDrmClient.cpp",
"IMediaDrmService.cpp",
- "MediaCasDefs.cpp",
+ "PluginMetricsReporting.cpp",
"SharedLibrary.cpp",
"DrmHal.cpp",
"CryptoHal.cpp",
+ "protos/plugin_metrics.proto",
],
+ proto: {
+ type: "lite",
+ },
+
shared_libs: [
"libbinder",
"libcutils",
"libdl",
"liblog",
+ "libmediametrics",
"libmediautils",
"libstagefright_foundation",
"libutils",
diff --git a/drm/libmediadrm/CasImpl.cpp b/drm/libmediadrm/CasImpl.cpp
deleted file mode 100644
index 1a33bb01f4..0000000000
--- a/drm/libmediadrm/CasImpl.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-
-/*
- * 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 "CasImpl"
-
-#include <android/media/ICasListener.h>
-#include <media/cas/CasAPI.h>
-#include <media/CasImpl.h>
-#include <media/SharedLibrary.h>
-#include <utils/Log.h>
-
-namespace android {
-
-static Status getBinderStatus(status_t err) {
- if (err == OK) {
- return Status::ok();
- }
- if (err == BAD_VALUE) {
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
- }
- if (err == INVALID_OPERATION) {
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
- }
- return Status::fromServiceSpecificError(err);
-}
-
-static String8 sessionIdToString(const CasSessionId &sessionId) {
- String8 result;
- for (size_t i = 0; i < sessionId.size(); i++) {
- result.appendFormat("%02x ", sessionId[i]);
- }
- if (result.isEmpty()) {
- result.append("(null)");
- }
- return result;
-}
-
-struct CasImpl::PluginHolder : public RefBase {
-public:
- explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
- ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
- CasPlugin* get() { return mPlugin; }
-
-private:
- CasPlugin *mPlugin;
- DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
-};
-
-CasImpl::CasImpl(const sp<ICasListener> &listener)
- : mPluginHolder(NULL), mListener(listener) {
- ALOGV("CTOR");
-}
-
-CasImpl::~CasImpl() {
- ALOGV("DTOR");
- release();
-}
-
-//static
-void CasImpl::OnEvent(
- void *appData,
- int32_t event,
- int32_t arg,
- uint8_t *data,
- size_t size) {
- if (appData == NULL) {
- ALOGE("Invalid appData!");
- return;
- }
- CasImpl *casImpl = static_cast<CasImpl *>(appData);
- casImpl->onEvent(event, arg, data, size);
-}
-
-void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
- mLibrary = library;
- mPluginHolder = new PluginHolder(plugin);
-}
-
-void CasImpl::onEvent(
- int32_t event, int32_t arg, uint8_t *data, size_t size) {
- if (mListener == NULL) {
- return;
- }
-
- std::unique_ptr<CasData> eventData;
- if (data != NULL && size > 0) {
- eventData.reset(new CasData(data, data + size));
- }
-
- mListener->onEvent(event, arg, eventData);
-}
-
-Status CasImpl::setPrivateData(const CasData& pvtData) {
- ALOGV("setPrivateData");
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
- return getBinderStatus(holder->get()->setPrivateData(pvtData));
-}
-
-Status CasImpl::openSession(CasSessionId* sessionId) {
- ALOGV("openSession");
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
- status_t err = holder->get()->openSession(sessionId);
-
- ALOGV("openSession: session opened, sessionId=%s",
- sessionIdToString(*sessionId).string());
-
- return getBinderStatus(err);
-}
-
-Status CasImpl::setSessionPrivateData(
- const CasSessionId &sessionId, const CasData& pvtData) {
- ALOGV("setSessionPrivateData: sessionId=%s",
- sessionIdToString(sessionId).string());
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
- return getBinderStatus(holder->get()->setSessionPrivateData(sessionId, pvtData));
-}
-
-Status CasImpl::closeSession(const CasSessionId &sessionId) {
- ALOGV("closeSession: sessionId=%s",
- sessionIdToString(sessionId).string());
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
- return getBinderStatus(holder->get()->closeSession(sessionId));
-}
-
-Status CasImpl::processEcm(const CasSessionId &sessionId, const ParcelableCasData& ecm) {
- ALOGV("processEcm: sessionId=%s",
- sessionIdToString(sessionId).string());
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
-
- return getBinderStatus(holder->get()->processEcm(sessionId, ecm));
-}
-
-Status CasImpl::processEmm(const ParcelableCasData& emm) {
- ALOGV("processEmm");
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
-
- return getBinderStatus(holder->get()->processEmm(emm));
-}
-
-Status CasImpl::sendEvent(
- int32_t event, int32_t arg, const ::std::unique_ptr<CasData> &eventData) {
- ALOGV("sendEvent");
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
-
- status_t err;
- if (eventData == nullptr) {
- err = holder->get()->sendEvent(event, arg, CasData());
- } else {
- err = holder->get()->sendEvent(event, arg, *eventData);
- }
- return getBinderStatus(err);
-}
-
-Status CasImpl::provision(const String16& provisionString) {
- ALOGV("provision: provisionString=%s", String8(provisionString).string());
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
-
- return getBinderStatus(holder->get()->provision(String8(provisionString)));
-}
-
-Status CasImpl::refreshEntitlements(
- int32_t refreshType, const ::std::unique_ptr<CasData> &refreshData) {
- ALOGV("refreshEntitlements");
- sp<PluginHolder> holder = mPluginHolder;
- if (holder == NULL) {
- return getBinderStatus(INVALID_OPERATION);
- }
-
- status_t err;
- if (refreshData == nullptr) {
- err = holder->get()->refreshEntitlements(refreshType, CasData());
- } else {
- err = holder->get()->refreshEntitlements(refreshType, *refreshData);
- }
- return getBinderStatus(err);
-}
-
-Status CasImpl::release() {
- ALOGV("release: plugin=%p",
- mPluginHolder == NULL ? mPluginHolder->get() : NULL);
- mPluginHolder.clear();
- return Status::ok();
-}
-
-} // namespace android
-
diff --git a/drm/libmediadrm/DescramblerImpl.cpp b/drm/libmediadrm/DescramblerImpl.cpp
deleted file mode 100644
index 5764669c81..0000000000
--- a/drm/libmediadrm/DescramblerImpl.cpp
+++ /dev/null
@@ -1,154 +0,0 @@
-
-/*
- * 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 "DescramblerImpl"
-
-#include <media/cas/DescramblerAPI.h>
-#include <media/DescramblerImpl.h>
-#include <media/SharedLibrary.h>
-#include <media/stagefright/foundation/AUtils.h>
-#include <binder/IMemory.h>
-#include <utils/Log.h>
-
-namespace android {
-
-static Status getBinderStatus(status_t err) {
- if (err == OK) {
- return Status::ok();
- }
- if (err == BAD_VALUE) {
- return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
- }
- if (err == INVALID_OPERATION) {
- return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
- }
- return Status::fromServiceSpecificError(err);
-}
-
-static String8 sessionIdToString(const CasSessionId &sessionId) {
- String8 result;
- for (size_t i = 0; i < sessionId.size(); i++) {
- result.appendFormat("%02x ", sessionId[i]);
- }
- if (result.isEmpty()) {
- result.append("(null)");
- }
- return result;
-}
-
-DescramblerImpl::DescramblerImpl(
- const sp<SharedLibrary>& library, DescramblerPlugin *plugin) :
- mLibrary(library), mPlugin(plugin) {
- ALOGV("CTOR: mPlugin=%p", mPlugin);
-}
-
-DescramblerImpl::~DescramblerImpl() {
- ALOGV("DTOR: mPlugin=%p", mPlugin);
- release();
-}
-
-Status DescramblerImpl::setMediaCasSession(const CasSessionId& sessionId) {
- ALOGV("setMediaCasSession: sessionId=%s",
- sessionIdToString(sessionId).string());
-
- return getBinderStatus(mPlugin->setMediaCasSession(sessionId));
-}
-
-Status DescramblerImpl::requiresSecureDecoderComponent(
- const String16& mime, bool *result) {
- *result = mPlugin->requiresSecureDecoderComponent(String8(mime));
-
- return getBinderStatus(OK);
-}
-
-static inline bool validateRangeForSize(
- uint64_t offset, uint64_t length, uint64_t size) {
- return isInRange<uint64_t, uint64_t>(0, size, offset, length);
-}
-
-Status DescramblerImpl::descramble(
- const DescrambleInfo& info, int32_t *result) {
- ALOGV("descramble");
-
- if (info.srcMem == NULL || info.srcMem->pointer() == NULL) {
- ALOGE("srcMem is invalid");
- return getBinderStatus(BAD_VALUE);
- }
-
- // use 64-bit here to catch bad subsample size that might be overflowing.
- uint64_t totalBytesInSubSamples = 0;
- for (size_t i = 0; i < info.numSubSamples; i++) {
- totalBytesInSubSamples += (uint64_t)info.subSamples[i].mNumBytesOfClearData +
- info.subSamples[i].mNumBytesOfEncryptedData;
- }
- // validate if the specified srcOffset and requested total subsample size
- // is consistent with the source shared buffer size.
- if (!validateRangeForSize(info.srcOffset, totalBytesInSubSamples, info.srcMem->size())) {
- ALOGE("Invalid srcOffset and subsample size: "
- "srcOffset %llu, totalBytesInSubSamples %llu, srcMem size %llu",
- (unsigned long long) info.srcOffset,
- (unsigned long long) totalBytesInSubSamples,
- (unsigned long long) info.srcMem->size());
- android_errorWriteLog(0x534e4554, "67962232");
- return getBinderStatus(BAD_VALUE);
- }
- void *dstPtr = NULL;
- if (info.dstType == DescrambleInfo::kDestinationTypeVmPointer) {
- // When using shared memory, src buffer is also used as dst
- dstPtr = info.srcMem->pointer();
-
- // In this case the dst and src would be the same buffer, need to validate
- // dstOffset against the buffer size too.
- if (!validateRangeForSize(info.dstOffset, totalBytesInSubSamples, info.srcMem->size())) {
- ALOGE("Invalid dstOffset and subsample size: "
- "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
- (unsigned long long) info.dstOffset,
- (unsigned long long) totalBytesInSubSamples,
- (unsigned long long) info.srcMem->size());
- android_errorWriteLog(0x534e4554, "67962232");
- return getBinderStatus(BAD_VALUE);
- }
- } else {
- dstPtr = info.dstPtr;
- }
-
- *result = mPlugin->descramble(
- info.dstType != DescrambleInfo::kDestinationTypeVmPointer,
- info.scramblingControl,
- info.numSubSamples,
- info.subSamples,
- info.srcMem->pointer(),
- info.srcOffset,
- dstPtr,
- info.dstOffset,
- NULL);
-
- return getBinderStatus(*result >= 0 ? OK : *result);
-}
-
-Status DescramblerImpl::release() {
- ALOGV("release: mPlugin=%p", mPlugin);
-
- if (mPlugin != NULL) {
- delete mPlugin;
- mPlugin = NULL;
- }
- return Status::ok();
-}
-
-} // namespace android
-
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 074489a93f..bc37557ed5 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -30,6 +30,7 @@
#include <media/DrmHal.h>
#include <media/DrmSessionClientInterface.h>
#include <media/DrmSessionManager.h>
+#include <media/PluginMetricsReporting.h>
#include <media/drm/DrmAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
@@ -194,7 +195,18 @@ DrmHal::DrmHal()
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
}
+void DrmHal::closeOpenSessions() {
+ if (mPlugin != NULL) {
+ for (size_t i = 0; i < mOpenSessions.size(); i++) {
+ mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
+ DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
+ }
+ }
+ mOpenSessions.clear();
+}
+
DrmHal::~DrmHal() {
+ closeOpenSessions();
DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
}
@@ -413,11 +425,12 @@ status_t DrmHal::createPlugin(const uint8_t uuid[16],
status_t DrmHal::destroyPlugin() {
Mutex::Autolock autoLock(mLock);
-
if (mInitCheck != OK) {
return mInitCheck;
}
+ closeOpenSessions();
+ reportMetrics();
setListener(NULL);
mInitCheck = NO_INIT;
@@ -471,6 +484,7 @@ status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
if (err == OK) {
DrmSessionManager::Instance()->addSession(getCallingPid(),
mDrmSessionClient, sessionId);
+ mOpenSessions.push(sessionId);
}
return err;
}
@@ -486,7 +500,14 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
if (status.isOk()) {
if (status == Status::OK) {
DrmSessionManager::Instance()->removeSession(sessionId);
+ for (size_t i = 0; i < mOpenSessions.size(); i++) {
+ if (mOpenSessions[i] == sessionId) {
+ mOpenSessions.removeAt(i);
+ break;
+ }
+ }
}
+ reportMetrics();
return toStatusT(status);
}
return DEAD_OBJECT;
@@ -740,6 +761,12 @@ status_t DrmHal::releaseAllSecureStops() {
status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
Mutex::Autolock autoLock(mLock);
+ return getPropertyStringInternal(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.
if (mInitCheck != OK) {
return mInitCheck;
@@ -761,6 +788,12 @@ status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
Mutex::Autolock autoLock(mLock);
+ return getPropertyByteArrayInternal(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.
if (mInitCheck != OK) {
return mInitCheck;
@@ -975,7 +1008,7 @@ status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
{
Mutex::Autolock autoLock(mLock);
-
+ closeOpenSessions();
setListener(NULL);
mInitCheck = NO_INIT;
@@ -997,4 +1030,20 @@ void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
}
}
+void DrmHal::reportMetrics() const
+{
+ Vector<uint8_t> metrics;
+ String8 vendor;
+ String8 description;
+ if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
+ getPropertyStringInternal(String8("description"), description) == OK &&
+ getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
+ status_t res = android::reportDrmPluginMetrics(
+ metrics, vendor, description);
+ if (res != OK) {
+ ALOGE("Metrics were retrieved but could not be reported: %i", res);
+ }
+ }
+}
+
} // namespace android
diff --git a/drm/libmediadrm/MediaCasDefs.cpp b/drm/libmediadrm/MediaCasDefs.cpp
deleted file mode 100644
index 9c2ba38fde..0000000000
--- a/drm/libmediadrm/MediaCasDefs.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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 "MediaCas"
-
-#include <media/MediaCasDefs.h>
-#include <utils/Log.h>
-#include <binder/IMemory.h>
-
-namespace android {
-namespace media {
-
-///////////////////////////////////////////////////////////////////////////////
-namespace MediaCas {
-
-status_t ParcelableCasData::readFromParcel(const Parcel* parcel) {
- return parcel->readByteVector(this);
-}
-
-status_t ParcelableCasData::writeToParcel(Parcel* parcel) const {
- return parcel->writeByteVector(*this);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-status_t ParcelableCasPluginDescriptor::readFromParcel(const Parcel* /*parcel*/) {
- ALOGE("CAPluginDescriptor::readFromParcel() shouldn't be called");
- return INVALID_OPERATION;
-}
-
-status_t ParcelableCasPluginDescriptor::writeToParcel(Parcel* parcel) const {
- status_t err = parcel->writeInt32(mCASystemId);
- if (err != NO_ERROR) {
- return err;
- }
- return parcel->writeString16(mName);
-}
-
-} // namespace MediaCas
-///////////////////////////////////////////////////////////////////////////////
-
-namespace MediaDescrambler {
-
-DescrambleInfo::DescrambleInfo() {}
-
-DescrambleInfo::~DescrambleInfo() {}
-
-status_t DescrambleInfo::readFromParcel(const Parcel* parcel) {
- status_t err = parcel->readInt32((int32_t*)&dstType);
- if (err != OK) {
- return err;
- }
- if (dstType != kDestinationTypeNativeHandle
- && dstType != kDestinationTypeVmPointer) {
- return BAD_VALUE;
- }
-
- err = parcel->readInt32((int32_t*)&scramblingControl);
- if (err != OK) {
- return err;
- }
-
- err = parcel->readUint32((uint32_t*)&numSubSamples);
- if (err != OK) {
- return err;
- }
- if (numSubSamples > 0xffff) {
- return BAD_VALUE;
- }
-
- subSamples = new DescramblerPlugin::SubSample[numSubSamples];
- if (subSamples == NULL) {
- return NO_MEMORY;
- }
-
- for (size_t i = 0; i < numSubSamples; i++) {
- err = parcel->readUint32(&subSamples[i].mNumBytesOfClearData);
- if (err != OK) {
- return err;
- }
- err = parcel->readUint32(&subSamples[i].mNumBytesOfEncryptedData);
- if (err != OK) {
- return err;
- }
- }
-
- srcMem = interface_cast<IMemory>(parcel->readStrongBinder());
- if (srcMem == NULL) {
- return BAD_VALUE;
- }
-
- err = parcel->readInt32(&srcOffset);
- if (err != OK) {
- return err;
- }
-
- native_handle_t *nativeHandle = NULL;
- if (dstType == kDestinationTypeNativeHandle) {
- nativeHandle = parcel->readNativeHandle();
- dstPtr = static_cast<void *>(nativeHandle);
- } else {
- dstPtr = NULL;
- }
-
- err = parcel->readInt32(&dstOffset);
- if (err != OK) {
- return err;
- }
-
- return OK;
-}
-
-status_t DescrambleInfo::writeToParcel(Parcel* parcel) const {
- if (dstType != kDestinationTypeNativeHandle
- && dstType != kDestinationTypeVmPointer) {
- return BAD_VALUE;
- }
-
- status_t err = parcel->writeInt32((int32_t)dstType);
- if (err != OK) {
- return err;
- }
-
- err = parcel->writeInt32(scramblingControl);
- if (err != OK) {
- return err;
- }
-
- err = parcel->writeUint32(numSubSamples);
- if (err != OK) {
- return err;
- }
-
- for (size_t i = 0; i < numSubSamples; i++) {
- err = parcel->writeUint32(subSamples[i].mNumBytesOfClearData);
- if (err != OK) {
- return err;
- }
- err = parcel->writeUint32(subSamples[i].mNumBytesOfEncryptedData);
- if (err != OK) {
- return err;
- }
- }
-
- err = parcel->writeStrongBinder(IInterface::asBinder(srcMem));
- if (err != OK) {
- return err;
- }
-
- err = parcel->writeInt32(srcOffset);
- if (err != OK) {
- return err;
- }
-
- if (dstType == kDestinationTypeNativeHandle) {
- parcel->writeNativeHandle(static_cast<native_handle_t *>(dstPtr));
- }
-
- err = parcel->writeInt32(dstOffset);
- if (err != OK) {
- return err;
- }
-
- return OK;
-}
-
-} // namespace MediaDescrambler
-
-} // namespace media
-} // namespace android
-
diff --git a/drm/libmediadrm/PluginMetricsReporting.cpp b/drm/libmediadrm/PluginMetricsReporting.cpp
new file mode 100644
index 0000000000..57ff5b8207
--- /dev/null
+++ b/drm/libmediadrm/PluginMetricsReporting.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "PluginMetricsReporting"
+#include <utils/Log.h>
+
+#include <media/PluginMetricsReporting.h>
+
+#include <media/MediaAnalyticsItem.h>
+
+#include "protos/plugin_metrics.pb.h"
+
+namespace android {
+
+namespace {
+
+using android::drm_metrics::MetricsGroup;
+using android::drm_metrics::MetricsGroup_Metric;
+using android::drm_metrics::MetricsGroup_Metric_MetricValue;
+
+const char* const kParentAttribute = "/parent/external";
+
+status_t reportMetricsGroup(const MetricsGroup& metricsGroup,
+ const String8& batchName,
+ const int64_t* parentId) {
+ MediaAnalyticsItem analyticsItem(batchName.c_str());
+ analyticsItem.generateSessionID();
+ int64_t sessionId = analyticsItem.getSessionID();
+ if (parentId != NULL) {
+ analyticsItem.setInt64(kParentAttribute, *parentId);
+ }
+
+ // Report the package name.
+ if (metricsGroup.has_app_package_name()) {
+ AString app_package_name(metricsGroup.app_package_name().c_str(),
+ metricsGroup.app_package_name().size());
+ analyticsItem.setPkgName(app_package_name);
+ }
+
+ for (int i = 0; i < metricsGroup.metric_size(); ++i) {
+ const MetricsGroup_Metric& metric = metricsGroup.metric(i);
+ if (!metric.has_name()) {
+ ALOGE("Metric with no name.");
+ return BAD_VALUE;
+ }
+
+ if (!metric.has_value()) {
+ ALOGE("Metric with no value.");
+ return BAD_VALUE;
+ }
+
+ const MetricsGroup_Metric_MetricValue& value = metric.value();
+ if (value.has_int_value()) {
+ analyticsItem.setInt64(metric.name().c_str(),
+ value.int_value());
+ } else if (value.has_double_value()) {
+ analyticsItem.setDouble(metric.name().c_str(),
+ value.double_value());
+ } else if (value.has_string_value()) {
+ analyticsItem.setCString(metric.name().c_str(),
+ value.string_value().c_str());
+ } else {
+ ALOGE("Metric Value with no actual value.");
+ return BAD_VALUE;
+ }
+ }
+
+ analyticsItem.setFinalized(true);
+ if (!analyticsItem.selfrecord()) {
+ // Note the cast to int is because we build on 32 and 64 bit.
+ // The cast prevents a peculiar printf problem where one format cannot
+ // satisfy both.
+ ALOGE("selfrecord() returned false. sessioId %d", (int) sessionId);
+ }
+
+ for (int i = 0; i < metricsGroup.metric_sub_group_size(); ++i) {
+ const MetricsGroup& subGroup = metricsGroup.metric_sub_group(i);
+ status_t res = reportMetricsGroup(subGroup, batchName, &sessionId);
+ if (res != OK) {
+ return res;
+ }
+ }
+
+ return OK;
+}
+
+String8 sanitize(const String8& input) {
+ // Filters the input string down to just alphanumeric characters.
+ String8 output;
+ for (size_t i = 0; i < input.size(); ++i) {
+ char candidate = input[i];
+ if ((candidate >= 'a' && candidate <= 'z') ||
+ (candidate >= 'A' && candidate <= 'Z') ||
+ (candidate >= '0' && candidate <= '9')) {
+ output.append(&candidate, 1);
+ }
+ }
+ return output;
+}
+
+} // namespace
+
+status_t reportDrmPluginMetrics(const Vector<uint8_t>& serializedMetrics,
+ const String8& vendor,
+ const String8& description) {
+ MetricsGroup root_metrics_group;
+ if (!root_metrics_group.ParseFromArray(serializedMetrics.array(),
+ serializedMetrics.size())) {
+ ALOGE("Failure to parse.");
+ return BAD_VALUE;
+ }
+
+ String8 name = String8::format("drm.vendor.%s.%s",
+ sanitize(vendor).c_str(),
+ sanitize(description).c_str());
+
+ return reportMetricsGroup(root_metrics_group, name, NULL);
+}
+
+} // namespace android
diff --git a/drm/libmediadrm/aidl/android/media/ICas.aidl b/drm/libmediadrm/aidl/android/media/ICas.aidl
deleted file mode 100644
index 97465937e6..0000000000
--- a/drm/libmediadrm/aidl/android/media/ICas.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-import android.media.MediaCas;
-
-/** @hide */
-interface ICas {
- void setPrivateData(in byte[] pvtData);
- byte[] openSession();
- void closeSession(in byte[] sessionId);
- void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
- void processEcm(in byte[] sessionId, in MediaCas.ParcelableCasData ecm);
- void processEmm(in MediaCas.ParcelableCasData emm);
- void sendEvent(int event, int arg, in @nullable byte[] eventData);
- void provision(String provisionString);
- void refreshEntitlements(int refreshType, in @nullable byte[] refreshData);
- void release();
-} \ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/ICasListener.aidl b/drm/libmediadrm/aidl/android/media/ICasListener.aidl
deleted file mode 100644
index 01a5abc883..0000000000
--- a/drm/libmediadrm/aidl/android/media/ICasListener.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-/** @hide */
-interface ICasListener {
- void onEvent(int event, int arg, in @nullable byte[] data);
-} \ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/IDescrambler.aidl b/drm/libmediadrm/aidl/android/media/IDescrambler.aidl
deleted file mode 100644
index fdf99eba62..0000000000
--- a/drm/libmediadrm/aidl/android/media/IDescrambler.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-import android.media.MediaDescrambler;
-
-/** @hide */
-interface IDescrambler {
- void setMediaCasSession(in byte[] sessionId);
- boolean requiresSecureDecoderComponent(String mime);
- int descramble(in MediaDescrambler.DescrambleInfo descrambleInfo);
- void release();
-} \ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl b/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl
deleted file mode 100644
index 44f6825188..0000000000
--- a/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-import android.media.IDescrambler;
-import android.media.ICas;
-import android.media.ICasListener;
-import android.media.MediaCas;
-
-/** @hide */
-interface IMediaCasService {
- MediaCas.ParcelableCasPluginDescriptor[] enumeratePlugins();
- boolean isSystemIdSupported(int CA_system_id);
- ICas createPlugin(int CA_system_id, ICasListener listener);
- boolean isDescramblerSupported(int CA_system_id);
- IDescrambler createDescrambler(int CA_system_id);
-}
-
diff --git a/drm/libmediadrm/aidl/android/media/MediaCas.aidl b/drm/libmediadrm/aidl/android/media/MediaCas.aidl
deleted file mode 100644
index cb8d0c65b0..0000000000
--- a/drm/libmediadrm/aidl/android/media/MediaCas.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-/** @hide */
-parcelable MediaCas.ParcelableCasPluginDescriptor cpp_header "media/MediaCasDefs.h";
-
-/** @hide */
-parcelable MediaCas.ParcelableCasData cpp_header "media/MediaCasDefs.h"; \ No newline at end of file
diff --git a/drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl b/drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl
deleted file mode 100644
index e7892442ef..0000000000
--- a/drm/libmediadrm/aidl/android/media/MediaDescrambler.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-package android.media;
-
-/** @hide */
-parcelable MediaDescrambler.DescrambleInfo cpp_header "media/MediaCasDefs.h"; \ No newline at end of file
diff --git a/drm/libmediadrm/protos/plugin_metrics.proto b/drm/libmediadrm/protos/plugin_metrics.proto
new file mode 100644
index 0000000000..7e3bcf5304
--- /dev/null
+++ b/drm/libmediadrm/protos/plugin_metrics.proto
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+
+package android.drm_metrics;
+
+// need this if we are using libprotobuf-cpp-2.3.0-lite
+option optimize_for = LITE_RUNTIME;
+
+// The MetricsGroup is a collection of metric name/value pair instances
+// that can be serialized and provided to a caller.
+message MetricsGroup {
+ message Metric {
+ message MetricValue {
+ // Exactly one of the following values must be set.
+ optional int64 int_value = 1;
+ optional double double_value = 2;
+ optional string string_value = 3;
+ }
+
+ // The name of the metric. Must be valid UTF-8. Required.
+ optional string name = 1;
+
+ // The value of the metric. Required.
+ optional MetricValue value = 2;
+ }
+
+ // The list of name/value pairs of metrics.
+ repeated Metric metric = 1;
+
+ // Allow multiple sub groups of metrics.
+ repeated MetricsGroup metric_sub_group = 2;
+
+ // Name of the application package associated with the metrics.
+ optional string app_package_name = 3;
+}
diff --git a/drm/mediacas/plugins/clearkey/Android.mk b/drm/mediacas/plugins/clearkey/Android.mk
index 8fd866ce8b..4b139a8fa7 100644
--- a/drm/mediacas/plugins/clearkey/Android.mk
+++ b/drm/mediacas/plugins/clearkey/Android.mk
@@ -28,8 +28,7 @@ LOCAL_SRC_FILES:= \
LOCAL_MODULE := libclearkeycasplugin
-#TODO: move this back to /vendor/lib after conversion to treble
-#LOCAL_PROPRIETARY_MODULE := true
+LOCAL_PROPRIETARY_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := mediacas
LOCAL_SHARED_LIBRARIES := \
@@ -39,6 +38,9 @@ LOCAL_SHARED_LIBRARIES := \
libstagefright_foundation \
libprotobuf-cpp-lite \
+LOCAL_HEADER_LIBRARIES := \
+ media_plugin_headers
+
LOCAL_STATIC_LIBRARIES := \
libjsmn \
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index 757219484c..50acc1dab5 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -121,7 +121,7 @@ status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
if (session.get() == nullptr) {
- return ERROR_DRM_SESSION_NOT_OPENED;
+ return ERROR_CAS_SESSION_NOT_OPENED;
}
ClearKeySessionLibrary::get()->destroySession(sessionId);
@@ -135,7 +135,7 @@ status_t ClearKeyCasPlugin::setSessionPrivateData(
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
if (session.get() == nullptr) {
- return ERROR_DRM_SESSION_NOT_OPENED;
+ return ERROR_CAS_SESSION_NOT_OPENED;
}
return OK;
}
@@ -146,7 +146,7 @@ status_t ClearKeyCasPlugin::processEcm(
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
if (session.get() == nullptr) {
- return ERROR_DRM_SESSION_NOT_OPENED;
+ return ERROR_CAS_SESSION_NOT_OPENED;
}
Mutex::Autolock lock(mKeyFetcherLock);
@@ -293,7 +293,7 @@ const static size_t kUserKeyLength = 16;
status_t ClearKeyCasSession::updateECM(
KeyFetcher *keyFetcher, void *ecm, size_t size) {
if (keyFetcher == nullptr) {
- return ERROR_DRM_NOT_PROVISIONED;
+ return ERROR_CAS_NOT_PROVISIONED;
}
if (size < kEcmHeaderLength) {
@@ -344,7 +344,7 @@ ssize_t ClearKeyCasSession::decrypt(
size_t numSubSamples, const DescramblerPlugin::SubSample *subSamples,
const void *srcPtr, void *dstPtr, AString * /* errorDetailMsg */) {
if (secure) {
- return ERROR_DRM_CANNOT_HANDLE;
+ return ERROR_CAS_CANNOT_HANDLE;
}
AES_KEY contentKey;
@@ -356,7 +356,7 @@ ssize_t ClearKeyCasSession::decrypt(
int32_t keyIndex = (scramblingControl & 1);
if (!mKeyInfo[keyIndex].valid) {
ALOGE("decrypt: key %d is invalid", keyIndex);
- return ERROR_DRM_DECRYPT;
+ return ERROR_CAS_DECRYPT;
}
contentKey = mKeyInfo[keyIndex].contentKey;
}
@@ -420,7 +420,7 @@ status_t ClearKeyDescramblerPlugin::setMediaCasSession(
if (session.get() == nullptr) {
ALOGE("ClearKeyDescramblerPlugin: session not found");
- return ERROR_DRM_SESSION_NOT_OPENED;
+ return ERROR_CAS_SESSION_NOT_OPENED;
}
std::atomic_store(&mCASSession, session);
@@ -448,7 +448,7 @@ ssize_t ClearKeyDescramblerPlugin::descramble(
if (session.get() == nullptr) {
ALOGE("Uninitialized CAS session!");
- return ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED;
+ return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED;
}
return session->decrypt(
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index 9cd77e9e41..6e1004caa1 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -48,24 +48,24 @@ JsonAssetLoader::~JsonAssetLoader() {
* Extract a clear key asset from a JSON string.
*
* Returns OK if a clear key asset is extracted successfully,
- * or ERROR_DRM_NO_LICENSE if the string doesn't contain a valid
+ * or ERROR_CAS_NO_LICENSE if the string doesn't contain a valid
* clear key asset.
*/
status_t JsonAssetLoader::extractAssetFromString(
const String8& jsonAssetString, Asset *asset) {
if (!parseJsonAssetString(jsonAssetString, &mJsonObjects)) {
- return ERROR_DRM_NO_LICENSE;
+ return ERROR_CAS_NO_LICENSE;
}
if (mJsonObjects.size() < 1) {
- return ERROR_DRM_NO_LICENSE;
+ return ERROR_CAS_NO_LICENSE;
}
if (!parseJsonObject(mJsonObjects[0], &mTokens))
- return ERROR_DRM_NO_LICENSE;
+ return ERROR_CAS_NO_LICENSE;
if (!findKey(mJsonObjects[0], asset)) {
- return ERROR_DRM_NO_LICENSE;
+ return ERROR_CAS_NO_LICENSE;
}
return OK;
}
diff --git a/drm/mediacas/plugins/clearkey/ecm_generator.h b/drm/mediacas/plugins/clearkey/ecm_generator.h
index 2ef06c4db8..5fbdea5870 100644
--- a/drm/mediacas/plugins/clearkey/ecm_generator.h
+++ b/drm/mediacas/plugins/clearkey/ecm_generator.h
@@ -29,7 +29,7 @@ using namespace std;
namespace android {
namespace clearkeycas {
enum {
- CLEARKEY_STATUS_BASE = ERROR_DRM_VENDOR_MAX,
+ CLEARKEY_STATUS_BASE = ERROR_CAS_VENDOR_MAX,
CLEARKEY_STATUS_INVALIDASSETID = CLEARKEY_STATUS_BASE - 1,
CLEARKEY_STATUS_INVALIDSYSTEMID = CLEARKEY_STATUS_BASE - 2,
CLEARKEY_STATUS_INVALID_PARAMETER = CLEARKEY_STATUS_BASE - 3,
diff --git a/drm/mediacas/plugins/clearkey/tests/Android.mk b/drm/mediacas/plugins/clearkey/tests/Android.mk
index cbf7be73a7..e1545afe00 100644
--- a/drm/mediacas/plugins/clearkey/tests/Android.mk
+++ b/drm/mediacas/plugins/clearkey/tests/Android.mk
@@ -21,12 +21,13 @@ LOCAL_SRC_FILES := \
ClearKeyFetcherTest.cpp
LOCAL_MODULE := ClearKeyFetcherTest
+LOCAL_VENDOR_MODULE := true
# LOCAL_LDFLAGS is needed here for the test to use the plugin, because
# the plugin is not in standard library search path. Without this .so
# loading fails at run-time (linking is okay).
LOCAL_LDFLAGS := \
- -Wl,--rpath,\$${ORIGIN}/../../../system/lib/mediacas -Wl,--enable-new-dtags
+ -Wl,--rpath,\$${ORIGIN}/../../../system/vendor/lib/mediacas -Wl,--enable-new-dtags
LOCAL_SHARED_LIBRARIES := \
libutils libclearkeycasplugin libstagefright_foundation libprotobuf-cpp-lite liblog
diff --git a/drm/mediacas/plugins/mock/Android.mk b/drm/mediacas/plugins/mock/Android.mk
index a97fac60cb..a1d61dae89 100644
--- a/drm/mediacas/plugins/mock/Android.mk
+++ b/drm/mediacas/plugins/mock/Android.mk
@@ -28,6 +28,8 @@ LOCAL_MODULE_RELATIVE_PATH := mediacas
LOCAL_SHARED_LIBRARIES := \
libutils liblog
+LOCAL_HEADER_LIBRARIES := media_plugin_headers
+
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/av/include \
$(TOP)/frameworks/native/include/media \
diff --git a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
index ed050f791a..0259a42a15 100644
--- a/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
+++ b/drm/mediadrm/plugins/clearkey/ClearKeyUUID.cpp
@@ -21,12 +21,19 @@
namespace clearkeydrm {
bool isClearKeyUUID(const uint8_t uuid[16]) {
- static const uint8_t kClearKeyUUID[16] = {
+ static const uint8_t kCommonPsshBoxUUID[16] = {
0x10,0x77,0xEF,0xEC,0xC0,0xB2,0x4D,0x02,
0xAC,0xE3,0x3C,0x1E,0x52,0xE2,0xFB,0x4B
};
- return !memcmp(uuid, kClearKeyUUID, sizeof(kClearKeyUUID));
+ // To be used in mpd to specify drm scheme for players
+ static const uint8_t kClearKeyUUID[16] = {
+ 0xE2,0x71,0x9D,0x58,0xA9,0x85,0xB3,0xC9,
+ 0x78,0x1A,0xB0,0x30,0xAF,0x78,0xD3,0x0E
+ };
+
+ return !memcmp(uuid, kCommonPsshBoxUUID, sizeof(kCommonPsshBoxUUID)) ||
+ !memcmp(uuid, kClearKeyUUID, sizeof(kClearKeyUUID));
}
} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
index 5fdac5cadf..ec07d87b1c 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
@@ -25,10 +25,28 @@
#include "Session.h"
+namespace {
+const android::String8 kStreaming("Streaming");
+const android::String8 kOffline("Offline");
+const android::String8 kTrue("True");
+
+const android::String8 kQueryKeyLicenseType("LicenseType");
+ // Value: "Streaming" or "Offline"
+const android::String8 kQueryKeyPlayAllowed("PlayAllowed");
+ // Value: "True" or "False"
+const android::String8 kQueryKeyRenewAllowed("RenewAllowed");
+ // Value: "True" or "False"
+};
+
namespace clearkeydrm {
using android::sp;
+DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
+ : mSessionLibrary(sessionLibrary) {
+ mPlayPolicy.clear();
+}
+
status_t DrmPlugin::openSession(Vector<uint8_t>& sessionId) {
sp<Session> session = mSessionLibrary->createSession();
sessionId = session->sessionId();
@@ -60,18 +78,28 @@ status_t DrmPlugin::getKeyRequest(
if (scope.size() == 0) {
return android::BAD_VALUE;
}
+
if (keyType != kKeyType_Streaming) {
return android::ERROR_DRM_CANNOT_HANDLE;
}
+
*keyRequestType = DrmPlugin::kKeyRequestType_Initial;
defaultUrl.clear();
sp<Session> session = mSessionLibrary->findSession(scope);
if (!session.get()) {
return android::ERROR_DRM_SESSION_NOT_OPENED;
}
+
return session->getKeyRequest(initData, mimeType, &request);
}
+void DrmPlugin::setPlayPolicy() {
+ mPlayPolicy.clear();
+ mPlayPolicy.add(kQueryKeyLicenseType, kStreaming);
+ mPlayPolicy.add(kQueryKeyPlayAllowed, kTrue);
+ mPlayPolicy.add(kQueryKeyRenewAllowed, kTrue);
+}
+
status_t DrmPlugin::provideKeyResponse(
const Vector<uint8_t>& scope,
const Vector<uint8_t>& response,
@@ -83,6 +111,8 @@ status_t DrmPlugin::provideKeyResponse(
if (!session.get()) {
return android::ERROR_DRM_SESSION_NOT_OPENED;
}
+
+ setPlayPolicy();
status_t res = session->provideKeyResponse(response);
if (res == android::OK) {
// This is for testing AMediaDrm_setOnEventListener only.
@@ -111,4 +141,18 @@ status_t DrmPlugin::getPropertyString(
return android::OK;
}
+status_t DrmPlugin::queryKeyStatus(
+ const Vector<uint8_t>& sessionId,
+ KeyedVector<String8, String8>& infoMap) const {
+
+ if (sessionId.size() == 0) {
+ return android::BAD_VALUE;
+ }
+
+ infoMap.clear();
+ for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
+ infoMap.add(mPlayPolicy.keyAt(i), mPlayPolicy.valueAt(i));
+ }
+ return android::OK;
+}
} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index 58421b9d01..f37a70699a 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -39,8 +39,8 @@ using android::Vector;
class DrmPlugin : public android::DrmPlugin {
public:
- explicit DrmPlugin(SessionLibrary* sessionLibrary)
- : mSessionLibrary(sessionLibrary) {}
+ explicit DrmPlugin(SessionLibrary* sessionLibrary);
+
virtual ~DrmPlugin() {}
virtual status_t openSession(Vector<uint8_t>& sessionId);
@@ -81,13 +81,7 @@ public:
virtual status_t queryKeyStatus(
const Vector<uint8_t>& sessionId,
- KeyedVector<String8, String8>& infoMap) const {
- if (sessionId.size() == 0) {
- return android::BAD_VALUE;
- }
- UNUSED(infoMap);
- return android::ERROR_DRM_CANNOT_HANDLE;
- }
+ KeyedVector<String8, String8>& infoMap) const;
virtual status_t getProvisionRequest(
const String8& cert_type,
@@ -248,9 +242,12 @@ public:
}
private:
- DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
+ void setPlayPolicy();
+ android::KeyedVector<android::String8, android::String8> mPlayPolicy;
SessionLibrary* mSessionLibrary;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin);
};
} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
index 6a4f8d5695..caff3939be 100644
--- a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
@@ -136,7 +136,7 @@ String8 InitDataParser::generateRequest(const Vector<const uint8_t*>& keyIds) {
AString encodedId;
for (size_t i = 0; i < keyIds.size(); ++i) {
encodedId.clear();
- android::encodeBase64(keyIds[i], kKeyIdSize, &encodedId);
+ android::encodeBase64Url(keyIds[i], kKeyIdSize, &encodedId);
if (i != 0) {
request.append(",");
}
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.bp b/drm/mediadrm/plugins/clearkey/tests/Android.bp
index ac57d653c6..0fcfc6436b 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.bp
@@ -34,4 +34,5 @@ cc_test {
"libstagefright_foundation",
"libutils",
],
+ header_libs: ["media_plugin_headers"],
}
diff --git a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
index 84ed242246..8c496566cc 100644
--- a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
+++ b/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
@@ -59,7 +59,7 @@ class InitDataParserTest : public ::testing::Test {
(size_t)requestString.find(kRequestSuffix));
for (size_t i = 0; i < expectedKeys.size(); ++i) {
AString encodedIdAString;
- android::encodeBase64(expectedKeys[i], kKeyIdSize,
+ android::encodeBase64Url(expectedKeys[i], kKeyIdSize,
&encodedIdAString);
String8 encodedId(encodedIdAString.c_str());
encodedId.removeAll(kBase64Padding);
@@ -231,5 +231,4 @@ TEST_F(InitDataParserTest, FailsForPsshBadKeyCount) {
attemptParseExpectingFailure(initData, kCencMimeType);
}
-
} // namespace clearkeydrm
diff --git a/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
index c3b0d84c61..d9f3ea6703 100644
--- a/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
+++ b/drm/mediadrm/plugins/clearkey/tests/JsonWebKeyUnittest.cpp
@@ -284,14 +284,14 @@ TEST_F(JsonWebKeyTest, ExtractKeys) {
"\"keys\":"
"[{"
"\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\""
- "\"k\":\"SGVsbG8gRnJpZW5kISE\""
+ "\"k\":\"SGVsbG8gRnJpZW5kICE-Pw\""
"\"kty\":\"oct\""
"\"alg\":\"A128KW1\""
"}"
"{"
"\"kty\":\"oct\""
"\"alg\":\"A128KW2\""
- "\"k\":\"SGVsbG8gRnJpZW5kIQ\""
+ "\"k\":\"SGVsbG8gRnJpZW5kICE_\""
"\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
"}"
"{"
@@ -303,7 +303,7 @@ TEST_F(JsonWebKeyTest, ExtractKeys) {
"{"
"\"alg\":\"A128KW3\""
"\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\""
- "\"k\":\"R29vZCBkYXkh\""
+ "\"k\":\"SGVsbG8gPz4-IEZyaWVuZCA_Pg\""
"\"kty\":\"oct\""
"}]"
"}");
@@ -313,8 +313,8 @@ TEST_F(JsonWebKeyTest, ExtractKeys) {
EXPECT_TRUE(keys.size() == 3);
const String8 clearKeys[] =
- { String8("Hello Friend!!"), String8("Hello Friend!"),
- String8("Good day!") };
+ { String8("Hello Friend !>?"), String8("Hello Friend !?"),
+ String8("Hello ?>> Friend ?>") };
verifyKeys(keys, clearKeys);
}
diff --git a/drm/mediadrm/plugins/mock/Android.bp b/drm/mediadrm/plugins/mock/Android.bp
index 7f448195c5..abd18840f3 100644
--- a/drm/mediadrm/plugins/mock/Android.bp
+++ b/drm/mediadrm/plugins/mock/Android.bp
@@ -22,6 +22,8 @@ cc_library_shared {
vendor: true,
relative_install_path: "mediadrm",
+ header_libs: ["media_plugin_headers"],
+
shared_libs: [
"libutils",
"liblog",