am e23212bc: Merge "Fix issue 3142808." into gingerbread
* commit 'e23212bc89bfcb3afbf8fdb5504556ead890e1a8':
Fix issue 3142808.
diff --git a/drm/common/Android.mk b/drm/common/Android.mk
new file mode 100644
index 0000000..c79a91a
--- /dev/null
+++ b/drm/common/Android.mk
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DrmConstraints.cpp \
+ DrmMetadata.cpp \
+ DrmConvertedStatus.cpp \
+ DrmEngineBase.cpp \
+ DrmInfo.cpp \
+ DrmInfoRequest.cpp \
+ DrmInfoStatus.cpp \
+ DrmRights.cpp \
+ DrmSupportInfo.cpp \
+ IDrmIOService.cpp \
+ IDrmManagerService.cpp \
+ IDrmServiceListener.cpp \
+ DrmInfoEvent.cpp \
+ ReadWriteUtils.cpp
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include
+
+LOCAL_MODULE:= libdrmframeworkcommon
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/common/DrmConstraints.cpp b/drm/common/DrmConstraints.cpp
new file mode 100644
index 0000000..4a4d798
--- /dev/null
+++ b/drm/common/DrmConstraints.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmConstraints.h>
+
+using namespace android;
+
+const String8 DrmConstraints::MAX_REPEAT_COUNT("max_repeat_count");
+const String8 DrmConstraints::REMAINING_REPEAT_COUNT("remaining_repeat_count");
+const String8 DrmConstraints::LICENSE_START_TIME("license_start_time");
+const String8 DrmConstraints::LICENSE_EXPIRY_TIME("license_expiry_time");
+const String8 DrmConstraints::LICENSE_AVAILABLE_TIME("license_available_time");
+const String8 DrmConstraints::EXTENDED_METADATA("extended_metadata");
+
+int DrmConstraints::getCount(void) const {
+ return mConstraintMap.size();
+}
+
+status_t DrmConstraints::put(const String8* key, const char* value) {
+ int length = strlen(value);
+ char* charValue = new char[length + 1];
+ if (NULL != charValue) {
+ strncpy(charValue, value, length);
+ charValue[length] = '\0';
+ mConstraintMap.add(*key, charValue);
+ }
+ return DRM_NO_ERROR;
+}
+
+String8 DrmConstraints::get(const String8& key) const {
+ if (NULL != getValue(&key)) {
+ return String8(getValue(&key));
+ }
+ return String8("");
+}
+
+const char* DrmConstraints::getValue(const String8* key) const {
+ if (NAME_NOT_FOUND != mConstraintMap.indexOfKey(*key)) {
+ return mConstraintMap.valueFor(*key);
+ }
+ return NULL;
+}
+
+const char* DrmConstraints::getAsByteArray(const String8* key) const {
+ return getValue(key);
+}
+
+bool DrmConstraints::KeyIterator::hasNext() {
+ return mIndex < mDrmConstraints->mConstraintMap.size();
+}
+
+const String8& DrmConstraints::KeyIterator::next() {
+ const String8& key = mDrmConstraints->mConstraintMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmConstraints::KeyIterator DrmConstraints::keyIterator() {
+ return KeyIterator(this);
+}
+
+DrmConstraints::KeyIterator::KeyIterator(const DrmConstraints::KeyIterator& keyIterator)
+ : mDrmConstraints(keyIterator.mDrmConstraints),
+ mIndex(keyIterator.mIndex) {
+}
+
+DrmConstraints::KeyIterator& DrmConstraints::KeyIterator::operator=(
+ const DrmConstraints::KeyIterator& keyIterator) {
+ mDrmConstraints = keyIterator.mDrmConstraints;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+
+DrmConstraints::Iterator DrmConstraints::iterator() {
+ return Iterator(this);
+}
+
+DrmConstraints::Iterator::Iterator(const DrmConstraints::Iterator& iterator) :
+ mDrmConstraints(iterator.mDrmConstraints),
+ mIndex(iterator.mIndex) {
+}
+
+DrmConstraints::Iterator& DrmConstraints::Iterator::operator=(
+ const DrmConstraints::Iterator& iterator) {
+ mDrmConstraints = iterator.mDrmConstraints;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmConstraints::Iterator::hasNext() {
+ return mIndex < mDrmConstraints->mConstraintMap.size();
+}
+
+String8 DrmConstraints::Iterator::next() {
+ String8 value = String8(mDrmConstraints->mConstraintMap.editValueAt(mIndex));
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmConvertedStatus.cpp b/drm/common/DrmConvertedStatus.cpp
new file mode 100644
index 0000000..5d035f5
--- /dev/null
+++ b/drm/common/DrmConvertedStatus.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmConvertedStatus.h>
+
+using namespace android;
+
+DrmConvertedStatus::DrmConvertedStatus(
+ int _statusCode, const DrmBuffer* _convertedData, int _offset) :
+ statusCode(_statusCode),
+ convertedData(_convertedData),
+ offset(_offset) {
+
+}
+
diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp
new file mode 100644
index 0000000..ac360eb
--- /dev/null
+++ b/drm/common/DrmEngineBase.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "DrmEngineBase.h"
+
+using namespace android;
+
+DrmEngineBase::DrmEngineBase() {
+
+}
+
+DrmEngineBase::~DrmEngineBase() {
+
+}
+
+DrmConstraints* DrmEngineBase::getConstraints(
+ int uniqueId, const String8* path, int action) {
+ return onGetConstraints(uniqueId, path, action);
+}
+
+DrmMetadata* DrmEngineBase::getMetadata(int uniqueId, const String8* path) {
+ return onGetMetadata(uniqueId, path);
+}
+
+status_t DrmEngineBase::initialize(int uniqueId) {
+ return onInitialize(uniqueId);
+}
+
+status_t DrmEngineBase::setOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ return onSetOnInfoListener(uniqueId, infoListener);
+}
+
+status_t DrmEngineBase::terminate(int uniqueId) {
+ return onTerminate(uniqueId);
+}
+
+bool DrmEngineBase::canHandle(int uniqueId, const String8& path) {
+ return onCanHandle(uniqueId, path);
+}
+
+DrmInfoStatus* DrmEngineBase::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ return onProcessDrmInfo(uniqueId, drmInfo);
+}
+
+status_t DrmEngineBase::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ return onSaveRights(uniqueId, drmRights, rightsPath, contentPath);
+}
+
+DrmInfo* DrmEngineBase::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ return onAcquireDrmInfo(uniqueId, drmInfoRequest);
+}
+
+String8 DrmEngineBase::getOriginalMimeType(int uniqueId, const String8& path) {
+ return onGetOriginalMimeType(uniqueId, path);
+}
+
+int DrmEngineBase::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ return onGetDrmObjectType(uniqueId, path, mimeType);
+}
+
+int DrmEngineBase::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ return onCheckRightsStatus(uniqueId, path, action);
+}
+
+status_t DrmEngineBase::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ return onConsumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+status_t DrmEngineBase::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ return onSetPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmEngineBase::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ return onValidateAction(uniqueId, path, action, description);
+}
+
+status_t DrmEngineBase::removeRights(int uniqueId, const String8& path) {
+ return onRemoveRights(uniqueId, path);
+}
+
+status_t DrmEngineBase::removeAllRights(int uniqueId) {
+ return onRemoveAllRights(uniqueId);
+}
+
+status_t DrmEngineBase::openConvertSession(int uniqueId, int convertId) {
+ return onOpenConvertSession(uniqueId, convertId);
+}
+
+DrmConvertedStatus* DrmEngineBase::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ return onConvertData(uniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmEngineBase::closeConvertSession(int uniqueId, int convertId) {
+ return onCloseConvertSession(uniqueId, convertId);
+}
+
+DrmSupportInfo* DrmEngineBase::getSupportInfo(int uniqueId) {
+ return onGetSupportInfo(uniqueId);
+}
+
+status_t DrmEngineBase::openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) {
+ return onOpenDecryptSession(uniqueId, decryptHandle, fd, offset, length);
+}
+
+status_t DrmEngineBase::openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
+ return onOpenDecryptSession(uniqueId, decryptHandle, uri);
+}
+
+status_t DrmEngineBase::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ return onCloseDecryptSession(uniqueId, decryptHandle);
+}
+
+status_t DrmEngineBase::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ return onInitializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmEngineBase::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ return onDecrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+}
+
+status_t DrmEngineBase::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ return onFinalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmEngineBase::pread(
+ int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) {
+ return onPread(uniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/common/DrmInfo.cpp b/drm/common/DrmInfo.cpp
new file mode 100644
index 0000000..ddcab33
--- /dev/null
+++ b/drm/common/DrmInfo.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmInfo.h>
+
+using namespace android;
+
+DrmInfo::DrmInfo(int infoType, const DrmBuffer& drmBuffer, const String8& mimeType) :
+ mInfoType(infoType),
+ mData(drmBuffer),
+ mMimeType(mimeType) {
+
+}
+
+int DrmInfo::getInfoType(void) const {
+ return mInfoType;
+}
+
+String8 DrmInfo::getMimeType(void) const {
+ return mMimeType;
+}
+
+const DrmBuffer& DrmInfo::getData(void) const {
+ return mData;
+}
+
+int DrmInfo::getCount(void) const {
+ return mAttributes.size();
+}
+
+status_t DrmInfo::put(const String8& key, const String8& value) {
+ mAttributes.add(key, value);
+ return DRM_NO_ERROR;
+}
+
+String8 DrmInfo::get(const String8& key) const {
+ if (NAME_NOT_FOUND != mAttributes.indexOfKey(key)) {
+ return mAttributes.valueFor(key);
+ }
+ return String8("");
+}
+
+int DrmInfo::indexOfKey(const String8& key) const {
+ return mAttributes.indexOfKey(key);
+}
+
+DrmInfo::KeyIterator DrmInfo::keyIterator() const {
+ return KeyIterator(this);
+}
+
+DrmInfo::Iterator DrmInfo::iterator() const {
+ return Iterator(this);
+}
+
+// KeyIterator implementation
+DrmInfo::KeyIterator::KeyIterator(const DrmInfo::KeyIterator& keyIterator) :
+ mDrmInfo(keyIterator.mDrmInfo), mIndex(keyIterator.mIndex) {
+
+}
+
+bool DrmInfo::KeyIterator::hasNext() {
+ return (mIndex < mDrmInfo->mAttributes.size());
+}
+
+const String8& DrmInfo::KeyIterator::next() {
+ const String8& key = mDrmInfo->mAttributes.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmInfo::KeyIterator& DrmInfo::KeyIterator::operator=(const DrmInfo::KeyIterator& keyIterator) {
+ mDrmInfo = keyIterator.mDrmInfo;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+// Iterator implementation
+DrmInfo::Iterator::Iterator(const DrmInfo::Iterator& iterator)
+ : mDrmInfo(iterator.mDrmInfo), mIndex(iterator.mIndex) {
+
+}
+
+DrmInfo::Iterator& DrmInfo::Iterator::operator=(const DrmInfo::Iterator& iterator) {
+ mDrmInfo = iterator.mDrmInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmInfo::Iterator::hasNext() {
+ return mIndex < mDrmInfo->mAttributes.size();
+}
+
+String8& DrmInfo::Iterator::next() {
+ String8& value = mDrmInfo->mAttributes.editValueAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmInfoEvent.cpp b/drm/common/DrmInfoEvent.cpp
new file mode 100644
index 0000000..8d115a8
--- /dev/null
+++ b/drm/common/DrmInfoEvent.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <utils/String8.h>
+#include <drm/DrmInfoEvent.h>
+
+using namespace android;
+
+DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8& message)
+ : mUniqueId(uniqueId),
+ mInfoType(infoType),
+ mMessage(message) {
+
+}
+
+int DrmInfoEvent::getUniqueId() const {
+ return mUniqueId;
+}
+
+int DrmInfoEvent::getType() const {
+ return mInfoType;
+}
+
+const String8& DrmInfoEvent::getMessage() const {
+ return mMessage;
+}
+
diff --git a/drm/common/DrmInfoRequest.cpp b/drm/common/DrmInfoRequest.cpp
new file mode 100644
index 0000000..a646859
--- /dev/null
+++ b/drm/common/DrmInfoRequest.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmInfoRequest.h>
+
+using namespace android;
+
+const String8 DrmInfoRequest::ACCOUNT_ID("account_id");
+const String8 DrmInfoRequest::SUBSCRIPTION_ID("subscription_id");
+
+DrmInfoRequest::DrmInfoRequest(int infoType, const String8& mimeType) :
+ mInfoType(infoType), mMimeType(mimeType) {
+
+}
+
+String8 DrmInfoRequest::getMimeType(void) const {
+ return mMimeType;
+}
+
+int DrmInfoRequest::getInfoType(void) const {
+ return mInfoType;
+}
+
+int DrmInfoRequest::getCount(void) const {
+ return mRequestInformationMap.size();
+}
+
+status_t DrmInfoRequest::put(const String8& key, const String8& value) {
+ mRequestInformationMap.add(key, value);
+ return DRM_NO_ERROR;
+}
+
+String8 DrmInfoRequest::get(const String8& key) const {
+ if (NAME_NOT_FOUND != mRequestInformationMap.indexOfKey(key)) {
+ return mRequestInformationMap.valueFor(key);
+ }
+ return String8("");
+}
+
+DrmInfoRequest::KeyIterator DrmInfoRequest::keyIterator() const {
+ return KeyIterator(this);
+}
+
+DrmInfoRequest::Iterator DrmInfoRequest::iterator() const {
+ return Iterator(this);
+}
+
+// KeyIterator implementation
+DrmInfoRequest::KeyIterator::KeyIterator(const DrmInfoRequest::KeyIterator& keyIterator)
+ : mDrmInfoRequest(keyIterator.mDrmInfoRequest),
+ mIndex(keyIterator.mIndex) {
+
+}
+
+bool DrmInfoRequest::KeyIterator::hasNext() {
+ return (mIndex < mDrmInfoRequest->mRequestInformationMap.size());
+}
+
+const String8& DrmInfoRequest::KeyIterator::next() {
+ const String8& key = mDrmInfoRequest->mRequestInformationMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmInfoRequest::KeyIterator& DrmInfoRequest::KeyIterator::operator=(
+ const DrmInfoRequest::KeyIterator& keyIterator) {
+ mDrmInfoRequest = keyIterator.mDrmInfoRequest;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+// Iterator implementation
+DrmInfoRequest::Iterator::Iterator(const DrmInfoRequest::Iterator& iterator) :
+ mDrmInfoRequest(iterator.mDrmInfoRequest), mIndex(iterator.mIndex) {
+}
+
+DrmInfoRequest::Iterator& DrmInfoRequest::Iterator::operator=(
+ const DrmInfoRequest::Iterator& iterator) {
+ mDrmInfoRequest = iterator.mDrmInfoRequest;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmInfoRequest::Iterator::hasNext() {
+ return mIndex < mDrmInfoRequest->mRequestInformationMap.size();
+}
+
+String8& DrmInfoRequest::Iterator::next() {
+ String8& value = mDrmInfoRequest->mRequestInformationMap.editValueAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmInfoStatus.cpp b/drm/common/DrmInfoStatus.cpp
new file mode 100644
index 0000000..8ec7311
--- /dev/null
+++ b/drm/common/DrmInfoStatus.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmInfoStatus.h>
+
+using namespace android;
+
+DrmInfoStatus::DrmInfoStatus(
+ int _statusCode, int _infoType, const DrmBuffer* _drmBuffer, const String8& _mimeType) :
+ statusCode(_statusCode),
+ infoType(_infoType),
+ drmBuffer(_drmBuffer),
+ mimeType(_mimeType) {
+
+}
+
diff --git a/drm/common/DrmMetadata.cpp b/drm/common/DrmMetadata.cpp
new file mode 100644
index 0000000..6cc5ec1
--- /dev/null
+++ b/drm/common/DrmMetadata.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmMetadata.h>
+
+using namespace android;
+
+int DrmMetadata::getCount(void) const {
+ return mMetadataMap.size();
+}
+
+status_t DrmMetadata::put(const String8* key,
+ const char* value) {
+ if((value != NULL) && (key != NULL)) {
+ int length = strlen(value);
+ char* charValue = new char[length + 1];
+
+ memcpy(charValue, value, length);
+ charValue[length] = '\0';
+ mMetadataMap.add(*key, charValue);
+ }
+ return NO_ERROR;
+}
+
+String8 DrmMetadata::get(const String8& key) const {
+ if (NULL != getValue(&key)) {
+ return String8(getValue(&key));
+ }
+ else {
+ return String8("");
+ }
+}
+
+const char* DrmMetadata::getValue(const String8* key) const {
+ if(key != NULL) {
+ if (NAME_NOT_FOUND != mMetadataMap.indexOfKey(*key)) {
+ return mMetadataMap.valueFor(*key);
+ }
+ else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+const char* DrmMetadata::getAsByteArray(const String8* key) const {
+ return getValue(key);
+}
+
+bool DrmMetadata::KeyIterator::hasNext() {
+ return mIndex < mDrmMetadata->mMetadataMap.size();
+}
+
+const String8& DrmMetadata::KeyIterator::next() {
+ const String8& key = mDrmMetadata->mMetadataMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmMetadata::KeyIterator DrmMetadata::keyIterator() {
+ return KeyIterator(this);
+}
+
+DrmMetadata::KeyIterator::KeyIterator(const DrmMetadata::KeyIterator& keyIterator) :
+ mDrmMetadata(keyIterator.mDrmMetadata),
+ mIndex(keyIterator.mIndex) {
+ LOGV("DrmMetadata::KeyIterator::KeyIterator");
+}
+
+DrmMetadata::KeyIterator& DrmMetadata::KeyIterator::operator=(const DrmMetadata::KeyIterator& keyIterator) {
+ LOGV("DrmMetadata::KeyIterator::operator=");
+ mDrmMetadata = keyIterator.mDrmMetadata;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+
+DrmMetadata::Iterator DrmMetadata::iterator() {
+ return Iterator(this);
+}
+
+DrmMetadata::Iterator::Iterator(const DrmMetadata::Iterator& iterator) :
+ mDrmMetadata(iterator.mDrmMetadata),
+ mIndex(iterator.mIndex) {
+ LOGV("DrmMetadata::Iterator::Iterator");
+}
+
+DrmMetadata::Iterator& DrmMetadata::Iterator::operator=(const DrmMetadata::Iterator& iterator) {
+ LOGV("DrmMetadata::Iterator::operator=");
+ mDrmMetadata = iterator.mDrmMetadata;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmMetadata::Iterator::hasNext() {
+ return mIndex < mDrmMetadata->mMetadataMap.size();
+}
+
+String8 DrmMetadata::Iterator::next() {
+ String8 value = String8(mDrmMetadata->mMetadataMap.editValueAt(mIndex));
+ mIndex++;
+ return value;
+}
diff --git a/drm/common/DrmRights.cpp b/drm/common/DrmRights.cpp
new file mode 100644
index 0000000..3aecb3d
--- /dev/null
+++ b/drm/common/DrmRights.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmRights.h>
+#include <ReadWriteUtils.h>
+
+using namespace android;
+
+DrmRights::DrmRights(const String8& rightsFilePath, const String8& mimeType,
+ const String8& accountId, const String8& subscriptionId) :
+ mMimeType(mimeType),
+ mAccountId(accountId),
+ mSubscriptionId(subscriptionId),
+ mRightsFromFile(NULL) {
+ int rightsLength = 0;
+ if (String8("") != rightsFilePath) {
+ rightsLength = ReadWriteUtils::readBytes(rightsFilePath, &mRightsFromFile);
+ }
+ mData = DrmBuffer(mRightsFromFile, rightsLength);
+}
+
+DrmRights::DrmRights(const DrmBuffer& rightsData, const String8& mimeType,
+ const String8& accountId, const String8& subscriptionId) :
+ mData(rightsData),
+ mMimeType(mimeType),
+ mAccountId(accountId),
+ mSubscriptionId(subscriptionId),
+ mRightsFromFile(NULL) {
+}
+
+DrmRights::~DrmRights() {
+ delete[] mRightsFromFile; mRightsFromFile = NULL;
+}
+
+const DrmBuffer& DrmRights::getData(void) const {
+ return mData;
+}
+
+String8 DrmRights::getMimeType(void) const {
+ return mMimeType;
+}
+
+String8 DrmRights::getAccountId(void) const {
+ return mAccountId;
+}
+
+String8 DrmRights::getSubscriptionId(void) const {
+ return mSubscriptionId;
+}
+
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
new file mode 100644
index 0000000..ffc8953
--- /dev/null
+++ b/drm/common/DrmSupportInfo.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmSupportInfo.h>
+
+using namespace android;
+
+DrmSupportInfo::DrmSupportInfo() {
+
+}
+
+DrmSupportInfo::DrmSupportInfo(const DrmSupportInfo& drmSupportInfo):
+ mMimeTypeVector(drmSupportInfo.mMimeTypeVector),
+ mFileSuffixVector(drmSupportInfo.mFileSuffixVector),
+ mDescription(drmSupportInfo.mDescription) {
+
+}
+
+bool DrmSupportInfo::operator<(const DrmSupportInfo& drmSupportInfo) const {
+ // Do we need to check mMimeTypeVector & mFileSuffixVector ?
+ // Note Vector doesn't overrides "<" operator
+ return mDescription < drmSupportInfo.mDescription;
+}
+
+bool DrmSupportInfo::operator==(const DrmSupportInfo& drmSupportInfo) const {
+ // Do we need to check mMimeTypeVector & mFileSuffixVector ?
+ // Note Vector doesn't overrides "==" operator
+ return (mDescription == drmSupportInfo.mDescription);
+}
+
+bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const {
+ for (unsigned int i = 0; i < mMimeTypeVector.size(); i++) {
+ const String8 item = mMimeTypeVector.itemAt(i);
+
+ if (String8("") != mimeType && item.find(mimeType) != -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool DrmSupportInfo::isSupportedFileSuffix(const String8& fileType) const {
+ for (unsigned int i = 0; i < mFileSuffixVector.size(); i++) {
+ const String8 item = mFileSuffixVector.itemAt(i);
+
+ if (String8("") != fileType && item.find(fileType) != -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+DrmSupportInfo& DrmSupportInfo::operator=(const DrmSupportInfo& drmSupportInfo) {
+ mMimeTypeVector = drmSupportInfo.mMimeTypeVector;
+ mFileSuffixVector = drmSupportInfo.mFileSuffixVector;
+ mDescription = drmSupportInfo.mDescription;
+ return *this;
+}
+
+int DrmSupportInfo::getMimeTypeCount(void) const {
+ return mMimeTypeVector.size();
+}
+
+int DrmSupportInfo::getFileSuffixCount(void) const {
+ return mFileSuffixVector.size();
+}
+
+status_t DrmSupportInfo::addMimeType(const String8& mimeType) {
+ mMimeTypeVector.push(mimeType);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmSupportInfo::addFileSuffix(const String8& fileSuffix) {
+ mFileSuffixVector.push(fileSuffix);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmSupportInfo::setDescription(const String8& description) {
+ mDescription = description;
+ return DRM_NO_ERROR;
+}
+
+String8 DrmSupportInfo::getDescription() const {
+ return mDescription;
+}
+
+DrmSupportInfo::FileSuffixIterator DrmSupportInfo::getFileSuffixIterator() {
+ return FileSuffixIterator(this);
+}
+
+DrmSupportInfo::MimeTypeIterator DrmSupportInfo::getMimeTypeIterator() {
+ return MimeTypeIterator(this);
+}
+
+DrmSupportInfo::FileSuffixIterator::FileSuffixIterator(
+ const DrmSupportInfo::FileSuffixIterator& iterator) :
+ mDrmSupportInfo(iterator.mDrmSupportInfo),
+ mIndex(iterator.mIndex) {
+
+}
+
+DrmSupportInfo::FileSuffixIterator& DrmSupportInfo::FileSuffixIterator::operator=(
+ const DrmSupportInfo::FileSuffixIterator& iterator) {
+ mDrmSupportInfo = iterator.mDrmSupportInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmSupportInfo::FileSuffixIterator::hasNext() {
+ return mIndex < mDrmSupportInfo->mFileSuffixVector.size();
+}
+
+String8& DrmSupportInfo::FileSuffixIterator::next() {
+ String8& value = mDrmSupportInfo->mFileSuffixVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
+DrmSupportInfo::MimeTypeIterator::MimeTypeIterator(
+ const DrmSupportInfo::MimeTypeIterator& iterator) :
+ mDrmSupportInfo(iterator.mDrmSupportInfo),
+ mIndex(iterator.mIndex) {
+
+}
+
+DrmSupportInfo::MimeTypeIterator& DrmSupportInfo::MimeTypeIterator::operator=(
+ const DrmSupportInfo::MimeTypeIterator& iterator) {
+ mDrmSupportInfo = iterator.mDrmSupportInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmSupportInfo::MimeTypeIterator::hasNext() {
+ return mIndex < mDrmSupportInfo->mMimeTypeVector.size();
+}
+
+String8& DrmSupportInfo::MimeTypeIterator::next() {
+ String8& value = mDrmSupportInfo->mMimeTypeVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/IDrmIOService.cpp b/drm/common/IDrmIOService.cpp
new file mode 100644
index 0000000..e44ca55
--- /dev/null
+++ b/drm/common/IDrmIOService.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmIOService.h"
+
+using namespace android;
+
+void BpDrmIOService::writeToFile(const String8& filePath, const String8& dataBuffer) {
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmIOService::getInterfaceDescriptor());
+ data.writeString8(filePath);
+ data.writeString8(dataBuffer);
+
+ remote()->transact(WRITE_TO_FILE, data, &reply);
+}
+
+String8 BpDrmIOService::readFromFile(const String8& filePath) {
+
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmIOService::getInterfaceDescriptor());
+ data.writeString8(filePath);
+
+ remote()->transact(READ_FROM_FILE, data, &reply);
+ return reply.readString8();
+}
+
+IMPLEMENT_META_INTERFACE(DrmIOService, "drm.IDrmIOService");
+
+status_t BnDrmIOService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+
+ switch (code) {
+ case WRITE_TO_FILE:
+ {
+ CHECK_INTERFACE(IDrmIOService, data, reply);
+
+ writeToFile(data.readString8(), data.readString8());
+ return DRM_NO_ERROR;
+ }
+
+ case READ_FROM_FILE:
+ {
+ CHECK_INTERFACE(IDrmIOService, data, reply);
+
+ String8 dataBuffer = readFromFile(data.readString8());
+ reply->writeString8(dataBuffer);
+ return DRM_NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
new file mode 100644
index 0000000..723b50e
--- /dev/null
+++ b/drm/common/IDrmManagerService.cpp
@@ -0,0 +1,1501 @@
+/*
+ * Copyright (C) 2010 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 "IDrmManagerService(Native)"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IPCThreadState.h>
+
+#include <drm/DrmInfo.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmRights.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+
+#include "IDrmManagerService.h"
+
+#define INVALID_BUFFER_LENGTH -1
+
+using namespace android;
+
+int BpDrmManagerService::addUniqueId(int uniqueId) {
+ LOGV("add uniqueid");
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(ADD_UNIQUEID, data, &reply);
+ return reply.readInt32();
+}
+
+void BpDrmManagerService::removeUniqueId(int uniqueId) {
+ LOGV("remove uniqueid");
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(REMOVE_UNIQUEID, data, &reply);
+}
+
+void BpDrmManagerService::addClient(int uniqueId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(ADD_CLIENT, data, &reply);
+}
+
+void BpDrmManagerService::removeClient(int uniqueId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(REMOVE_CLIENT, data, &reply);
+}
+
+status_t BpDrmManagerService::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ LOGV("setDrmServiceListener");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeStrongBinder(drmServiceListener->asBinder());
+ remote()->transact(SET_DRM_SERVICE_LISTENER, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ LOGV("Install DRM Engine");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(drmEngineFile);
+
+ remote()->transact(INSTALL_DRM_ENGINE, data, &reply);
+ return reply.readInt32();
+}
+
+DrmConstraints* BpDrmManagerService::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ LOGV("Get Constraints");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(*path);
+ data.writeInt32(action);
+
+ remote()->transact(GET_CONSTRAINTS_FROM_CONTENT, data, &reply);
+
+ DrmConstraints* drmConstraints = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling Drm Constraints
+ drmConstraints = new DrmConstraints();
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmConstraints->put(&key, data);
+ }
+ }
+ return drmConstraints;
+}
+
+DrmMetadata* BpDrmManagerService::getMetadata(int uniqueId, const String8* path) {
+ LOGV("Get Metadata");
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ DrmMetadata* drmMetadata = NULL;
+ data.writeString8(*path);
+ remote()->transact(GET_METADATA_FROM_CONTENT, data, &reply);
+
+ if (0 != reply.dataAvail()) {
+ //Filling Drm Metadata
+ drmMetadata = new DrmMetadata();
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmMetadata->put(&key, data);
+ }
+ }
+ return drmMetadata;
+}
+
+bool BpDrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Can Handle");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeString8(path);
+ data.writeString8(mimeType);
+
+ remote()->transact(CAN_HANDLE, data, &reply);
+
+ return static_cast<bool>(reply.readInt32());
+}
+
+DrmInfoStatus* BpDrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ LOGV("Process DRM Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling DRM info
+ data.writeInt32(drmInfo->getInfoType());
+ const DrmBuffer dataBuffer = drmInfo->getData();
+ const int dataBufferSize = dataBuffer.length;
+ data.writeInt32(dataBufferSize);
+ if (0 < dataBufferSize) {
+ data.write(dataBuffer.data, dataBufferSize);
+ }
+ data.writeString8(drmInfo->getMimeType());
+
+ data.writeInt32(drmInfo->getCount());
+ DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
+
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ data.writeString8(key);
+ const String8 value = drmInfo->get(key);
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+
+ remote()->transact(PROCESS_DRM_INFO, data, &reply);
+
+ DrmInfoStatus* drmInfoStatus = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Info Status
+ const int statusCode = reply.readInt32();
+ const int infoType = reply.readInt32();
+ const String8 mimeType = reply.readString8();
+
+ DrmBuffer* drmBuffer = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmBuffer = new DrmBuffer(data, bufferSize);
+ }
+ drmInfoStatus = new DrmInfoStatus(statusCode, infoType, drmBuffer, mimeType);
+ }
+ return drmInfoStatus;
+}
+
+DrmInfo* BpDrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) {
+ LOGV("Acquire DRM Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling DRM Info Request
+ data.writeInt32(drmInforequest->getInfoType());
+ data.writeString8(drmInforequest->getMimeType());
+
+ data.writeInt32(drmInforequest->getCount());
+ DrmInfoRequest::KeyIterator keyIt = drmInforequest->keyIterator();
+
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ data.writeString8(key);
+ const String8 value = drmInforequest->get(key);
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+
+ remote()->transact(ACQUIRE_DRM_INFO, data, &reply);
+
+ DrmInfo* drmInfo = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Info
+ const int infoType = reply.readInt32();
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmInfo = new DrmInfo(infoType, DrmBuffer(data, bufferSize), reply.readString8());
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const String8 value(reply.readString8());
+ drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+ }
+ return drmInfo;
+}
+
+status_t BpDrmManagerService::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ LOGV("Save Rights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling Drm Rights
+ const DrmBuffer dataBuffer = drmRights.getData();
+ data.writeInt32(dataBuffer.length);
+ data.write(dataBuffer.data, dataBuffer.length);
+
+ const String8 mimeType = drmRights.getMimeType();
+ data.writeString8((mimeType == String8("")) ? String8("NULL") : mimeType);
+
+ const String8 accountId = drmRights.getAccountId();
+ data.writeString8((accountId == String8("")) ? String8("NULL") : accountId);
+
+ const String8 subscriptionId = drmRights.getSubscriptionId();
+ data.writeString8((subscriptionId == String8("")) ? String8("NULL") : subscriptionId);
+
+ data.writeString8((rightsPath == String8("")) ? String8("NULL") : rightsPath);
+ data.writeString8((contentPath == String8("")) ? String8("NULL") : contentPath);
+
+ remote()->transact(SAVE_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+String8 BpDrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) {
+ LOGV("Get Original MimeType");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+
+ remote()->transact(GET_ORIGINAL_MIMETYPE, data, &reply);
+ return reply.readString8();
+}
+
+int BpDrmManagerService::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Get Drm object type");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeString8(mimeType);
+
+ remote()->transact(GET_DRM_OBJECT_TYPE, data, &reply);
+
+ return reply.readInt32();
+}
+
+int BpDrmManagerService::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ LOGV("checkRightsStatus");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeInt32(action);
+
+ remote()->transact(CHECK_RIGHTS_STATUS, data, &reply);
+
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ LOGV("consumeRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(action);
+ data.writeInt32(static_cast< int>(reserve));
+
+ remote()->transact(CONSUME_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ LOGV("setPlaybackStatus");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(playbackStatus);
+ data.writeInt32(position);
+
+ remote()->transact(SET_PLAYBACK_STATUS, data, &reply);
+ return reply.readInt32();
+}
+
+bool BpDrmManagerService::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ LOGV("validateAction");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeInt32(action);
+ data.writeInt32(description.outputType);
+ data.writeInt32(description.configuration);
+
+ remote()->transact(VALIDATE_ACTION, data, &reply);
+
+ return static_cast<bool>(reply.readInt32());
+}
+
+status_t BpDrmManagerService::removeRights(int uniqueId, const String8& path) {
+ LOGV("removeRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+
+ remote()->transact(REMOVE_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::removeAllRights(int uniqueId) {
+ LOGV("removeAllRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(REMOVE_ALL_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+int BpDrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
+ LOGV("openConvertSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(mimeType);
+
+ remote()->transact(OPEN_CONVERT_SESSION, data, &reply);
+ return reply.readInt32();
+}
+
+DrmConvertedStatus* BpDrmManagerService::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ LOGV("convertData");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeInt32(convertId);
+ data.writeInt32(inputData->length);
+ data.write(inputData->data, inputData->length);
+
+ remote()->transact(CONVERT_DATA, data, &reply);
+
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Converted Status
+ const int statusCode = reply.readInt32();
+ const int offset = reply.readInt32();
+
+ DrmBuffer* convertedData = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ convertedData = new DrmBuffer(data, bufferSize);
+ }
+ drmConvertedStatus = new DrmConvertedStatus(statusCode, convertedData, offset);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* BpDrmManagerService::closeConvertSession(int uniqueId, int convertId) {
+ LOGV("closeConvertSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeInt32(convertId);
+
+ remote()->transact(CLOSE_CONVERT_SESSION, data, &reply);
+
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Converted Status
+ const int statusCode = reply.readInt32();
+ const int offset = reply.readInt32();
+
+ DrmBuffer* convertedData = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ convertedData = new DrmBuffer(data, bufferSize);
+ }
+ drmConvertedStatus = new DrmConvertedStatus(statusCode, convertedData, offset);
+ }
+ return drmConvertedStatus;
+}
+
+status_t BpDrmManagerService::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ LOGV("Get All Support Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(GET_ALL_SUPPORT_INFO, data, &reply);
+
+ //Filling DRM Support Info
+ const int arraySize = reply.readInt32();
+ if (0 < arraySize) {
+ *drmSupportInfoArray = new DrmSupportInfo[arraySize];
+
+ for (int index = 0; index < arraySize; ++index) {
+ DrmSupportInfo drmSupportInfo;
+
+ const int fileSuffixVectorSize = reply.readInt32();
+ for (int i = 0; i < fileSuffixVectorSize; ++i) {
+ drmSupportInfo.addFileSuffix(reply.readString8());
+ }
+
+ const int mimeTypeVectorSize = reply.readInt32();
+ for (int i = 0; i < mimeTypeVectorSize; ++i) {
+ drmSupportInfo.addMimeType(reply.readString8());
+ }
+
+ drmSupportInfo.setDescription(reply.readString8());
+ (*drmSupportInfoArray)[index] = drmSupportInfo;
+ }
+ }
+ *length = arraySize;
+ return reply.readInt32();
+}
+
+DecryptHandle* BpDrmManagerService::openDecryptSession(
+ int uniqueId, int fd, int offset, int length) {
+ LOGV("Entering BpDrmManagerService::openDecryptSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeFileDescriptor(fd);
+ data.writeInt32(offset);
+ data.writeInt32(length);
+
+ remote()->transact(OPEN_DECRYPT_SESSION, data, &reply);
+
+ DecryptHandle* handle = NULL;
+ if (0 != reply.dataAvail()) {
+ handle = new DecryptHandle();
+ handle->decryptId = reply.readInt32();
+ handle->mimeType = reply.readString8();
+ handle->decryptApiType = reply.readInt32();
+ handle->status = reply.readInt32();
+ handle->decryptInfo = NULL;
+ if (0 != reply.dataAvail()) {
+ handle->decryptInfo = new DecryptInfo();
+ handle->decryptInfo->decryptBufferLength = reply.readInt32();
+ }
+ } else {
+ LOGE("no decryptHandle is generated in service side");
+ }
+ return handle;
+}
+
+DecryptHandle* BpDrmManagerService::openDecryptSession(int uniqueId, const char* uri) {
+ LOGV("Entering BpDrmManagerService::openDecryptSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(String8(uri));
+
+ remote()->transact(OPEN_DECRYPT_SESSION_FROM_URI, data, &reply);
+
+ DecryptHandle* handle = NULL;
+ if (0 != reply.dataAvail()) {
+ handle = new DecryptHandle();
+ handle->decryptId = reply.readInt32();
+ handle->mimeType = reply.readString8();
+ handle->decryptApiType = reply.readInt32();
+ handle->status = reply.readInt32();
+ handle->decryptInfo = NULL;
+ if (0 != reply.dataAvail()) {
+ handle->decryptInfo = new DecryptInfo();
+ handle->decryptInfo->decryptBufferLength = reply.readInt32();
+ }
+ } else {
+ LOGE("no decryptHandle is generated in service side");
+ }
+ return handle;
+}
+
+status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ LOGV("closeDecryptSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ LOGV("deleting decryptInfo");
+ delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
+ }
+ delete decryptHandle; decryptHandle = NULL;
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ LOGV("initializeDecryptUnit");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+ data.writeInt32(decryptUnitId);
+
+ data.writeInt32(headerInfo->length);
+ data.write(headerInfo->data, headerInfo->length);
+
+ remote()->transact(INITIALIZE_DECRYPT_UNIT, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ LOGV("decrypt");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(decryptUnitId);
+ data.writeInt32((*decBuffer)->length);
+
+ data.writeInt32(encBuffer->length);
+ data.write(encBuffer->data, encBuffer->length);
+
+ if (NULL != IV) {
+ data.writeInt32(IV->length);
+ data.write(IV->data, IV->length);
+ }
+
+ remote()->transact(DECRYPT, data, &reply);
+
+ const status_t status = reply.readInt32();
+ LOGV("Return value of decrypt() is %d", status);
+
+ const int size = reply.readInt32();
+ (*decBuffer)->length = size;
+ reply.read((void *)(*decBuffer)->data, size);
+
+ return status;
+}
+
+status_t BpDrmManagerService::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ LOGV("finalizeDecryptUnit");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(decryptUnitId);
+
+ remote()->transact(FINALIZE_DECRYPT_UNIT, data, &reply);
+ return reply.readInt32();
+}
+
+ssize_t BpDrmManagerService::pread(
+ int uniqueId, DecryptHandle* decryptHandle, void* buffer,
+ ssize_t numBytes, off_t offset) {
+ LOGV("read");
+ Parcel data, reply;
+ int result;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(numBytes);
+ data.writeInt32(offset);
+
+ remote()->transact(PREAD, data, &reply);
+ result = reply.readInt32();
+ if (0 < result) {
+ reply.read(buffer, result);
+ }
+ return result;
+}
+
+IMPLEMENT_META_INTERFACE(DrmManagerService, "drm.IDrmManagerService");
+
+status_t BnDrmManagerService::onTransact(
+ uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags) {
+ LOGV("Entering BnDrmManagerService::onTransact with code %d", code);
+
+ switch (code) {
+ case ADD_UNIQUEID:
+ {
+ LOGV("BnDrmManagerService::onTransact :ADD_UNIQUEID");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ int uniqueId = addUniqueId(data.readInt32());
+ reply->writeInt32(uniqueId);
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_UNIQUEID:
+ {
+ LOGV("BnDrmManagerService::onTransact :REMOVE_UNIQUEID");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ removeUniqueId(data.readInt32());
+ return DRM_NO_ERROR;
+ }
+
+ case ADD_CLIENT:
+ {
+ LOGV("BnDrmManagerService::onTransact :ADD_CLIENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ addClient(data.readInt32());
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_CLIENT:
+ {
+ LOGV("BnDrmManagerService::onTransact :REMOVE_CLIENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ removeClient(data.readInt32());
+ return DRM_NO_ERROR;
+ }
+
+ case SET_DRM_SERVICE_LISTENER:
+ {
+ LOGV("BnDrmManagerService::onTransact :SET_DRM_SERVICE_LISTENER");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const sp<IDrmServiceListener> drmServiceListener
+ = interface_cast<IDrmServiceListener> (data.readStrongBinder());
+
+ status_t status = setDrmServiceListener(uniqueId, drmServiceListener);
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case INSTALL_DRM_ENGINE:
+ {
+ LOGV("BnDrmManagerService::onTransact :INSTALL_DRM_ENGINE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ status_t status = installDrmEngine(data.readInt32(), data.readString8());
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_CONSTRAINTS_FROM_CONTENT:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_CONSTRAINTS_FROM_CONTENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+
+ DrmConstraints* drmConstraints = getConstraints(uniqueId, &path, data.readInt32());
+
+ if (NULL != drmConstraints) {
+ //Filling DRM Constraints contents
+ reply->writeInt32(drmConstraints->getCount());
+
+ DrmConstraints::KeyIterator keyIt = drmConstraints->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const char* value = drmConstraints->getAsByteArray(&key);
+ int bufferSize = 0;
+ if (NULL != value) {
+ bufferSize = strlen(value);
+ }
+ reply->writeInt32(bufferSize + 1);
+ reply->write(value, bufferSize + 1);
+ }
+ }
+ delete drmConstraints; drmConstraints = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case GET_METADATA_FROM_CONTENT:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_METADATA_FROM_CONTENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+
+ DrmMetadata* drmMetadata = getMetadata(uniqueId, &path);
+ if (NULL != drmMetadata) {
+ //Filling DRM Metadata contents
+ reply->writeInt32(drmMetadata->getCount());
+
+ DrmMetadata::KeyIterator keyIt = drmMetadata->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const char* value = drmMetadata->getAsByteArray(&key);
+ int bufferSize = 0;
+ if (NULL != value) {
+ bufferSize = strlen(value);
+ reply->writeInt32(bufferSize + 1);
+ reply->write(value, bufferSize + 1);
+ } else {
+ reply->writeInt32(0);
+ }
+ }
+ }
+ delete drmMetadata; drmMetadata = NULL;
+ return NO_ERROR;
+ }
+
+ case CAN_HANDLE:
+ {
+ LOGV("BnDrmManagerService::onTransact :CAN_HANDLE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const String8 mimeType = data.readString8();
+
+ bool result = canHandle(uniqueId, path, mimeType);
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case PROCESS_DRM_INFO:
+ {
+ LOGV("BnDrmManagerService::onTransact :PROCESS_DRM_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM info
+ const int infoType = data.readInt32();
+ const int bufferSize = data.readInt32();
+ char* buffer = NULL;
+ if (0 < bufferSize) {
+ buffer = (char *)data.readInplace(bufferSize);
+ }
+ const DrmBuffer drmBuffer(buffer, bufferSize);
+ DrmInfo* drmInfo = new DrmInfo(infoType, drmBuffer, data.readString8());
+
+ const int size = data.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(data.readString8());
+ const String8 value(data.readString8());
+ drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+
+ DrmInfoStatus* drmInfoStatus = processDrmInfo(uniqueId, drmInfo);
+
+ if (NULL != drmInfoStatus) {
+ //Filling DRM Info Status contents
+ reply->writeInt32(drmInfoStatus->statusCode);
+ reply->writeInt32(drmInfoStatus->infoType);
+ reply->writeString8(drmInfoStatus->mimeType);
+
+ if (NULL != drmInfoStatus->drmBuffer) {
+ const DrmBuffer* drmBuffer = drmInfoStatus->drmBuffer;
+ const int bufferSize = drmBuffer->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(drmBuffer->data, bufferSize);
+ }
+ delete [] drmBuffer->data;
+ delete drmBuffer; drmBuffer = NULL;
+ }
+ }
+ delete drmInfo; drmInfo = NULL;
+ delete drmInfoStatus; drmInfoStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case ACQUIRE_DRM_INFO:
+ {
+ LOGV("BnDrmManagerService::onTransact :ACQUIRE_DRM_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM info Request
+ DrmInfoRequest* drmInfoRequest = new DrmInfoRequest(data.readInt32(), data.readString8());
+
+ const int size = data.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(data.readString8());
+ const String8 value(data.readString8());
+ drmInfoRequest->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+
+ DrmInfo* drmInfo = acquireDrmInfo(uniqueId, drmInfoRequest);
+
+ if (NULL != drmInfo) {
+ //Filling DRM Info
+ const DrmBuffer drmBuffer = drmInfo->getData();
+ reply->writeInt32(drmInfo->getInfoType());
+
+ const int bufferSize = drmBuffer.length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(drmBuffer.data, bufferSize);
+ }
+ reply->writeString8(drmInfo->getMimeType());
+ reply->writeInt32(drmInfo->getCount());
+
+ DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const String8 value = drmInfo->get(key);
+ reply->writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+ delete [] drmBuffer.data;
+ }
+ delete drmInfoRequest; drmInfoRequest = NULL;
+ delete drmInfo; drmInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case SAVE_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :SAVE_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM Rights
+ const int bufferSize = data.readInt32();
+ const DrmBuffer drmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ const String8 mimeType(data.readString8());
+ const String8 accountId(data.readString8());
+ const String8 subscriptionId(data.readString8());
+ const String8 rightsPath(data.readString8());
+ const String8 contentPath(data.readString8());
+
+ DrmRights drmRights(drmBuffer,
+ ((mimeType == String8("NULL")) ? String8("") : mimeType),
+ ((accountId == String8("NULL")) ? String8("") : accountId),
+ ((subscriptionId == String8("NULL")) ? String8("") : subscriptionId));
+
+ const status_t status = saveRights(uniqueId, drmRights,
+ ((rightsPath == String8("NULL")) ? String8("") : rightsPath),
+ ((contentPath == String8("NULL")) ? String8("") : contentPath));
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_ORIGINAL_MIMETYPE:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_ORIGINAL_MIMETYPE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const String8 originalMimeType = getOriginalMimeType(data.readInt32(), data.readString8());
+
+ reply->writeString8(originalMimeType);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_DRM_OBJECT_TYPE:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_DRM_OBJECT_TYPE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int drmObjectType
+ = getDrmObjectType(data.readInt32(), data.readString8(), data.readString8());
+
+ reply->writeInt32(drmObjectType);
+ return DRM_NO_ERROR;
+ }
+
+ case CHECK_RIGHTS_STATUS:
+ {
+ LOGV("BnDrmManagerService::onTransact :CHECK_RIGHTS_STATUS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int result
+ = checkRightsStatus(data.readInt32(), data.readString8(), data.readInt32());
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case CONSUME_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :CONSUME_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ const status_t status
+ = consumeRights(uniqueId, &handle, data.readInt32(),
+ static_cast<bool>(data.readInt32()));
+ reply->writeInt32(status);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case SET_PLAYBACK_STATUS:
+ {
+ LOGV("BnDrmManagerService::onTransact :SET_PLAYBACK_STATUS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ const status_t status
+ = setPlaybackStatus(uniqueId, &handle, data.readInt32(), data.readInt32());
+ reply->writeInt32(status);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case VALIDATE_ACTION:
+ {
+ LOGV("BnDrmManagerService::onTransact :VALIDATE_ACTION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ bool result = validateAction(
+ data.readInt32(),
+ data.readString8(),
+ data.readInt32(),
+ ActionDescription(data.readInt32(), data.readInt32()));
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :REMOVE_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const status_t status = removeRights(data.readInt32(), data.readString8());
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_ALL_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :REMOVE_ALL_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const status_t status = removeAllRights(data.readInt32());
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_CONVERT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :OPEN_CONVERT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int convertId = openConvertSession(data.readInt32(), data.readString8());
+
+ reply->writeInt32(convertId);
+ return DRM_NO_ERROR;
+ }
+
+ case CONVERT_DATA:
+ {
+ LOGV("BnDrmManagerService::onTransact :CONVERT_DATA");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int convertId = data.readInt32();
+
+ //Filling input data
+ const int bufferSize = data.readInt32();
+ DrmBuffer* inputData = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ DrmConvertedStatus* drmConvertedStatus = convertData(uniqueId, convertId, inputData);
+
+ if (NULL != drmConvertedStatus) {
+ //Filling Drm Converted Ststus
+ reply->writeInt32(drmConvertedStatus->statusCode);
+ reply->writeInt32(drmConvertedStatus->offset);
+
+ if (NULL != drmConvertedStatus->convertedData) {
+ const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
+ const int bufferSize = convertedData->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(convertedData->data, bufferSize);
+ }
+ delete [] convertedData->data;
+ delete convertedData; convertedData = NULL;
+ }
+ }
+ delete inputData; inputData = NULL;
+ delete drmConvertedStatus; drmConvertedStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case CLOSE_CONVERT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :CLOSE_CONVERT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ DrmConvertedStatus* drmConvertedStatus
+ = closeConvertSession(data.readInt32(), data.readInt32());
+
+ if (NULL != drmConvertedStatus) {
+ //Filling Drm Converted Ststus
+ reply->writeInt32(drmConvertedStatus->statusCode);
+ reply->writeInt32(drmConvertedStatus->offset);
+
+ if (NULL != drmConvertedStatus->convertedData) {
+ const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
+ const int bufferSize = convertedData->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(convertedData->data, bufferSize);
+ }
+ delete [] convertedData->data;
+ delete convertedData; convertedData = NULL;
+ }
+ }
+ delete drmConvertedStatus; drmConvertedStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case GET_ALL_SUPPORT_INFO:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_ALL_SUPPORT_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ int length = 0;
+ DrmSupportInfo* drmSupportInfoArray = NULL;
+
+ status_t status = getAllSupportInfo(uniqueId, &length, &drmSupportInfoArray);
+
+ reply->writeInt32(length);
+ for (int i = 0; i < length; ++i) {
+ DrmSupportInfo drmSupportInfo = drmSupportInfoArray[i];
+
+ reply->writeInt32(drmSupportInfo.getFileSuffixCount());
+ DrmSupportInfo::FileSuffixIterator fileSuffixIt
+ = drmSupportInfo.getFileSuffixIterator();
+ while (fileSuffixIt.hasNext()) {
+ reply->writeString8(fileSuffixIt.next());
+ }
+
+ reply->writeInt32(drmSupportInfo.getMimeTypeCount());
+ DrmSupportInfo::MimeTypeIterator mimeTypeIt = drmSupportInfo.getMimeTypeIterator();
+ while (mimeTypeIt.hasNext()) {
+ reply->writeString8(mimeTypeIt.next());
+ }
+ reply->writeString8(drmSupportInfo.getDescription());
+ }
+ delete [] drmSupportInfoArray; drmSupportInfoArray = NULL;
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_DECRYPT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int fd = data.readFileDescriptor();
+
+ DecryptHandle* handle
+ = openDecryptSession(uniqueId, fd, data.readInt32(), data.readInt32());
+
+ if (NULL != handle) {
+ reply->writeInt32(handle->decryptId);
+ reply->writeString8(handle->mimeType);
+ reply->writeInt32(handle->decryptApiType);
+ reply->writeInt32(handle->status);
+ if (NULL != handle->decryptInfo) {
+ reply->writeInt32(handle->decryptInfo->decryptBufferLength);
+ delete handle->decryptInfo; handle->decryptInfo = NULL;
+ }
+ } else {
+ LOGE("NULL decryptHandle is returned");
+ }
+ delete handle; handle = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_DECRYPT_SESSION_FROM_URI:
+ {
+ LOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION_FROM_URI");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 uri = data.readString8();
+
+ DecryptHandle* handle = openDecryptSession(uniqueId, uri.string());
+
+ if (NULL != handle) {
+ reply->writeInt32(handle->decryptId);
+ reply->writeString8(handle->mimeType);
+ reply->writeInt32(handle->decryptApiType);
+ reply->writeInt32(handle->status);
+ if (NULL != handle->decryptInfo) {
+ reply->writeInt32(handle->decryptInfo->decryptBufferLength);
+ delete handle->decryptInfo; handle->decryptInfo = NULL;
+ }
+ } else {
+ LOGE("NULL decryptHandle is returned");
+ }
+ delete handle; handle = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case CLOSE_DECRYPT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :CLOSE_DECRYPT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle* handle = new DecryptHandle();
+ handle->decryptId = data.readInt32();
+ handle->mimeType = data.readString8();
+ handle->decryptApiType = data.readInt32();
+ handle->status = data.readInt32();
+ handle->decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle->decryptInfo = new DecryptInfo();
+ handle->decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ const status_t status = closeDecryptSession(uniqueId, handle);
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case INITIALIZE_DECRYPT_UNIT:
+ {
+ LOGV("BnDrmManagerService::onTransact :INITIALIZE_DECRYPT_UNIT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+ const int decryptUnitId = data.readInt32();
+
+ //Filling Header info
+ const int bufferSize = data.readInt32();
+ DrmBuffer* headerInfo = NULL;
+ headerInfo = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ const status_t status
+ = initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo);
+ reply->writeInt32(status);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ delete headerInfo; headerInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case DECRYPT:
+ {
+ LOGV("BnDrmManagerService::onTransact :DECRYPT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+ const int decryptUnitId = data.readInt32();
+ const int decBufferSize = data.readInt32();
+
+ const int encBufferSize = data.readInt32();
+ DrmBuffer* encBuffer
+ = new DrmBuffer((char *)data.readInplace(encBufferSize), encBufferSize);
+
+ char* buffer = NULL;
+ buffer = new char[decBufferSize];
+ DrmBuffer* decBuffer = new DrmBuffer(buffer, decBufferSize);
+
+ DrmBuffer* IV = NULL;
+ if (0 != data.dataAvail()) {
+ const int ivBufferlength = data.readInt32();
+ IV = new DrmBuffer((char *)data.readInplace(ivBufferlength), ivBufferlength);
+ }
+
+ const status_t status
+ = decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer, IV);
+
+ reply->writeInt32(status);
+
+ const int size = decBuffer->length;
+ reply->writeInt32(size);
+ reply->write(decBuffer->data, size);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ delete encBuffer; encBuffer = NULL;
+ delete decBuffer; decBuffer = NULL;
+ delete [] buffer; buffer = NULL;
+ delete IV; IV = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case FINALIZE_DECRYPT_UNIT:
+ {
+ LOGV("BnDrmManagerService::onTransact :FINALIZE_DECRYPT_UNIT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ const status_t status = finalizeDecryptUnit(uniqueId, &handle, data.readInt32());
+ reply->writeInt32(status);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case PREAD:
+ {
+ LOGV("BnDrmManagerService::onTransact :READ");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ const int numBytes = data.readInt32();
+ char* buffer = new char[numBytes];
+
+ const off_t offset = data.readInt32();
+
+ ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset);
+ reply->writeInt32(result);
+ if (0 < result) {
+ reply->write(buffer, result);
+ }
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ delete [] buffer, buffer = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/IDrmServiceListener.cpp b/drm/common/IDrmServiceListener.cpp
new file mode 100644
index 0000000..6eeea40
--- /dev/null
+++ b/drm/common/IDrmServiceListener.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <drm/drm_framework_common.h>
+#include <drm/DrmInfoEvent.h>
+#include "IDrmServiceListener.h"
+
+using namespace android;
+
+status_t BpDrmServiceListener::notify(const DrmInfoEvent& event) {
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmServiceListener::getInterfaceDescriptor());
+ data.writeInt32(event.getUniqueId());
+ data.writeInt32(event.getType());
+ data.writeString8(event.getMessage());
+
+ remote()->transact(NOTIFY, data, &reply);
+ return reply.readInt32();
+}
+
+IMPLEMENT_META_INTERFACE(DrmServiceListener, "drm.IDrmServiceListener");
+
+status_t BnDrmServiceListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+
+ switch (code) {
+ case NOTIFY:
+ {
+ CHECK_INTERFACE(IDrmServiceListener, data, reply);
+ int uniqueId = data.readInt32();
+ int type = data.readInt32();
+ const String8& message = data.readString8();
+
+ status_t status = notify(DrmInfoEvent(uniqueId, type, message));
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/ReadWriteUtils.cpp b/drm/common/ReadWriteUtils.cpp
new file mode 100644
index 0000000..7ec4fa2
--- /dev/null
+++ b/drm/common/ReadWriteUtils.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 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 "ReadWriteUtils"
+#include <utils/Log.h>
+
+#include <ReadWriteUtils.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define FAILURE -1
+
+String8 ReadWriteUtils::readBytes(const String8& filePath) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "r");
+
+ String8 string("");
+ if (NULL != file) {
+ int fd = fileno(file);
+ struct stat sb;
+
+ if (fstat(fd, &sb) == 0 && sb.st_size > 0) {
+ int length = sb.st_size;
+ char* bytes = new char[length];
+ if (length == read(fd, (void*) bytes, length)) {
+ string.append(bytes, length);
+ }
+ delete bytes;
+ }
+ fclose(file);
+ }
+ return string;
+}
+
+int ReadWriteUtils::readBytes(const String8& filePath, char** buffer) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "r");
+ int length = 0;
+
+ if (NULL != file) {
+ int fd = fileno(file);
+ struct stat sb;
+
+ if (fstat(fd, &sb) == 0 && sb.st_size > 0) {
+ length = sb.st_size;
+ *buffer = new char[length];
+ if (length != read(fd, (void*) *buffer, length)) {
+ length = FAILURE;
+ }
+ }
+ fclose(file);
+ }
+ return length;
+}
+
+void ReadWriteUtils::writeToFile(const String8& filePath, const String8& data) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "w+");
+
+ if (NULL != file) {
+ int fd = fileno(file);
+
+ int size = data.size();
+ if (FAILURE != ftruncate(fd, size)) {
+ if (size != write(fd, data.string(), size)) {
+ LOGE("Failed to write the data to: %s", filePath.string());
+ }
+ }
+ fclose(file);
+ }
+}
+
+void ReadWriteUtils::appendToFile(const String8& filePath, const String8& data) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "a+");
+
+ if (NULL != file) {
+ int fd = fileno(file);
+
+ int size = data.size();
+ if (size != write(fd, data.string(), size)) {
+ LOGE("Failed to write the data to: %s", filePath.string());
+ }
+ fclose(file);
+ }
+}
+
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
new file mode 100644
index 0000000..5df2ff8
--- /dev/null
+++ b/drm/drmserver/Android.mk
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main_drmserver.cpp \
+ DrmManager.cpp \
+ DrmManagerService.cpp \
+ StringTokenizer.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libbinder
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include
+
+LOCAL_MODULE:= drmserver
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
new file mode 100644
index 0000000..537791c
--- /dev/null
+++ b/drm/drmserver/DrmManager.cpp
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2010 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 "DrmManager(Native)"
+#include "utils/Log.h"
+
+#include <utils/String8.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <drm/DrmConvertedStatus.h>
+#include <IDrmEngine.h>
+
+#include "DrmManager.h"
+#include "ReadWriteUtils.h"
+
+#define DECRYPT_FILE_ERROR -1
+
+using namespace android;
+
+Vector<int> DrmManager::mUniqueIdVector;
+const String8 DrmManager::EMPTY_STRING("");
+
+DrmManager::DrmManager() :
+ mDecryptSessionId(0),
+ mConvertId(0) {
+
+}
+
+DrmManager::~DrmManager() {
+
+}
+
+int DrmManager::addUniqueId(int uniqueId) {
+ if (0 == uniqueId) {
+ int temp = 0;
+ bool foundUniqueId = false;
+ srand(time(NULL));
+
+ while (!foundUniqueId) {
+ const int size = mUniqueIdVector.size();
+ temp = rand() % 100;
+
+ int index = 0;
+ for (; index < size; ++index) {
+ if (mUniqueIdVector.itemAt(index) == temp) {
+ foundUniqueId = false;
+ break;
+ }
+ }
+ if (index == size) {
+ foundUniqueId = true;
+ }
+ }
+ uniqueId = temp;
+ }
+ mUniqueIdVector.push(uniqueId);
+ return uniqueId;
+}
+
+void DrmManager::removeUniqueId(int uniqueId) {
+ for (unsigned int i = 0; i < mUniqueIdVector.size(); i++) {
+ if (uniqueId == mUniqueIdVector.itemAt(i)) {
+ mUniqueIdVector.removeAt(i);
+ break;
+ }
+ }
+}
+
+status_t DrmManager::loadPlugIns() {
+ String8 pluginDirPath("/system/lib/drm/plugins/native");
+ return loadPlugIns(pluginDirPath);
+}
+
+status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
+ if (mSupportInfoToPlugInIdMap.isEmpty()) {
+ mPlugInManager.loadPlugIns(plugInDirPath);
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+ for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+ String8 plugInPath = plugInPathList[i];
+ DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
+ if (NULL != info) {
+ mSupportInfoToPlugInIdMap.add(*info, plugInPath);
+ }
+ }
+ }
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManager::unloadPlugIns() {
+ mConvertSessionMap.clear();
+ mDecryptSessionMap.clear();
+ mPlugInManager.unloadPlugIns();
+ mSupportInfoToPlugInIdMap.clear();
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManager::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ Mutex::Autolock _l(mLock);
+ mServiceListeners.add(uniqueId, drmServiceListener);
+ return DRM_NO_ERROR;
+}
+
+void DrmManager::addClient(int uniqueId) {
+ if (!mSupportInfoToPlugInIdMap.isEmpty()) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.initialize(uniqueId);
+ rDrmEngine.setOnInfoListener(uniqueId, this);
+ }
+ }
+}
+
+void DrmManager::removeClient(int uniqueId) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.terminate(uniqueId);
+ }
+}
+
+DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getConstraints(uniqueId, path, action);
+ }
+ return NULL;
+}
+
+DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getMetadata(uniqueId, path);
+ }
+ return NULL;
+}
+
+status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) {
+ mPlugInManager.loadPlugIn(absolutePath);
+
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath);
+ rDrmEngine.initialize(uniqueId);
+ rDrmEngine.setOnInfoListener(uniqueId, this);
+
+ DrmSupportInfo* info = rDrmEngine.getSupportInfo(0);
+ mSupportInfoToPlugInIdMap.add(*info, absolutePath);
+
+ return DRM_NO_ERROR;
+}
+
+bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ const String8 plugInId = getSupportedPlugInId(mimeType);
+ bool result = (EMPTY_STRING != plugInId) ? true : false;
+
+ if (0 < path.length()) {
+ if (result) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.canHandle(uniqueId, path);
+ } else {
+ result = canHandle(uniqueId, path);
+ }
+ }
+ return result;
+}
+
+DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.processDrmInfo(uniqueId, drmInfo);
+ }
+ return NULL;
+}
+
+bool DrmManager::canHandle(int uniqueId, const String8& path) {
+ bool result = false;
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
+ result = rDrmEngine.canHandle(uniqueId, path);
+
+ if (result) {
+ break;
+ }
+ }
+ return result;
+}
+
+DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
+ }
+ return NULL;
+}
+
+status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType());
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
+ }
+ return result;
+}
+
+String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getOriginalMimeType(uniqueId, path);
+ }
+ return EMPTY_STRING;
+}
+
+int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
+ }
+ return DrmObjectType::UNKNOWN;
+}
+
+int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.checkRightsStatus(uniqueId, path, action);
+ }
+ return RightsStatus::RIGHTS_INVALID;
+}
+
+status_t DrmManager::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve);
+ }
+ return result;
+}
+
+status_t DrmManager::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+ }
+ return result;
+}
+
+bool DrmManager::validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.validateAction(uniqueId, path, action, description);
+ }
+ return false;
+}
+
+status_t DrmManager::removeRights(int uniqueId, const String8& path) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.removeRights(uniqueId, path);
+ }
+ return result;
+}
+
+status_t DrmManager::removeAllRights(int uniqueId) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+ status_t result = DRM_ERROR_UNKNOWN;
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ result = rDrmEngine.removeAllRights(uniqueId);
+ if (DRM_NO_ERROR != result) {
+ break;
+ }
+ }
+ return result;
+}
+
+int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
+ int convertId = -1;
+
+ const String8 plugInId = getSupportedPlugInId(mimeType);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+
+ if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) {
+ Mutex::Autolock _l(mConvertLock);
+ ++mConvertId;
+ convertId = mConvertId;
+ mConvertSessionMap.add(convertId, &rDrmEngine);
+ }
+ }
+ return convertId;
+}
+
+DrmConvertedStatus* DrmManager::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ DrmConvertedStatus *drmConvertedStatus = NULL;
+
+ if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
+ drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) {
+ DrmConvertedStatus *drmConvertedStatus = NULL;
+
+ if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
+ drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId);
+ mConvertSessionMap.removeItem(convertId);
+ }
+ return drmConvertedStatus;
+}
+
+status_t DrmManager::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+ int size = plugInPathList.size();
+ int validPlugins = 0;
+
+ if (0 < size) {
+ Vector<DrmSupportInfo> drmSupportInfoList;
+
+ for (int i = 0; i < size; ++i) {
+ String8 plugInPath = plugInPathList[i];
+ DrmSupportInfo* drmSupportInfo
+ = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
+ if (NULL != drmSupportInfo) {
+ drmSupportInfoList.add(*drmSupportInfo);
+ delete drmSupportInfo; drmSupportInfo = NULL;
+ }
+ }
+
+ validPlugins = drmSupportInfoList.size();
+ if (0 < validPlugins) {
+ *drmSupportInfoArray = new DrmSupportInfo[validPlugins];
+ for (int i = 0; i < validPlugins; ++i) {
+ (*drmSupportInfoArray)[i] = drmSupportInfoList[i];
+ }
+ }
+ }
+ *length = validPlugins;
+ return DRM_NO_ERROR;
+}
+
+DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, int offset, int length) {
+ Mutex::Autolock _l(mDecryptLock);
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ DecryptHandle* handle = new DecryptHandle();
+ if (NULL != handle) {
+ handle->decryptId = mDecryptSessionId + 1;
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ String8 plugInId = plugInIdList.itemAt(index);
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length);
+
+ if (DRM_NO_ERROR == result) {
+ ++mDecryptSessionId;
+ mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ break;
+ }
+ }
+ }
+ if (DRM_NO_ERROR != result) {
+ delete handle; handle = NULL;
+ LOGE("DrmManager::openDecryptSession: no capable plug-in found");
+ }
+ return handle;
+}
+
+DecryptHandle* DrmManager::openDecryptSession(int uniqueId, const char* uri) {
+ Mutex::Autolock _l(mDecryptLock);
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ DecryptHandle* handle = new DecryptHandle();
+ if (NULL != handle) {
+ handle->decryptId = mDecryptSessionId + 1;
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ String8 plugInId = plugInIdList.itemAt(index);
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.openDecryptSession(uniqueId, handle, uri);
+
+ if (DRM_NO_ERROR == result) {
+ ++mDecryptSessionId;
+ mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ break;
+ }
+ }
+ }
+ if (DRM_NO_ERROR != result) {
+ delete handle; handle = NULL;
+ LOGE("DrmManager::openDecryptSession: no capable plug-in found");
+ }
+ return handle;
+}
+
+status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ Mutex::Autolock _l(mDecryptLock);
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->closeDecryptSession(uniqueId, decryptHandle);
+ if (DRM_NO_ERROR == result) {
+ mDecryptSessionMap.removeItem(decryptHandle->decryptId);
+ }
+ }
+ return result;
+}
+
+status_t DrmManager::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+ }
+ return result;
+}
+
+status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->decrypt(
+ uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+ }
+ return result;
+}
+
+status_t DrmManager::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+ }
+ return result;
+}
+
+ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ ssize_t result = DECRYPT_FILE_ERROR;
+
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+ }
+ return result;
+}
+
+String8 DrmManager::getSupportedPlugInId(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ String8 plugInId("");
+
+ if (EMPTY_STRING != mimeType) {
+ plugInId = getSupportedPlugInId(mimeType);
+ } else {
+ plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ }
+ return plugInId;
+}
+
+String8 DrmManager::getSupportedPlugInId(const String8& mimeType) {
+ String8 plugInId("");
+
+ if (EMPTY_STRING != mimeType) {
+ for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+ const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
+
+ if (drmSupportInfo.isSupportedMimeType(mimeType)) {
+ plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
+ break;
+ }
+ }
+ }
+ return plugInId;
+}
+
+String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
+ String8 plugInId("");
+ const String8 fileSuffix = path.getPathExtension();
+
+ for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+ const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
+
+ if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
+ String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
+ IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key);
+
+ if (drmEngine.canHandle(uniqueId, path)) {
+ plugInId = key;
+ break;
+ }
+ }
+ }
+ return plugInId;
+}
+
+void DrmManager::onInfo(const DrmInfoEvent& event) {
+ Mutex::Autolock _l(mLock);
+ for (unsigned int index = 0; index < mServiceListeners.size(); index++) {
+ int uniqueId = mServiceListeners.keyAt(index);
+
+ if (uniqueId == event.getUniqueId()) {
+ sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId);
+ serviceListener->notify(event);
+ }
+ }
+}
+
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
new file mode 100644
index 0000000..4dcfa72
--- /dev/null
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2010 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 "DrmManagerService(Native)"
+#include <utils/Log.h>
+
+#include <private/android_filesystem_config.h>
+
+#include <errno.h>
+#include <utils/threads.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <sys/stat.h>
+#include "DrmManagerService.h"
+#include "DrmManager.h"
+
+using namespace android;
+
+static Vector<uid_t> trustedUids;
+
+static bool isProtectedCallAllowed() {
+ // TODO
+ // Following implementation is just for reference.
+ // Each OEM manufacturer should implement/replace with their own solutions.
+ bool result = false;
+
+ IPCThreadState* ipcState = IPCThreadState::self();
+ uid_t uid = ipcState->getCallingUid();
+
+ for (unsigned int i = 0; i < trustedUids.size(); ++i) {
+ if (trustedUids[i] == uid) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+void DrmManagerService::instantiate() {
+ LOGV("instantiate");
+ defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
+
+ if (0 >= trustedUids.size()) {
+ // TODO
+ // Following implementation is just for reference.
+ // Each OEM manufacturer should implement/replace with their own solutions.
+
+ // Add trusted uids here
+ trustedUids.push(AID_MEDIA);
+ }
+}
+
+DrmManagerService::DrmManagerService() :
+ mDrmManager(NULL) {
+ LOGV("created");
+ mDrmManager = new DrmManager();
+ mDrmManager->loadPlugIns();
+}
+
+DrmManagerService::~DrmManagerService() {
+ LOGV("Destroyed");
+ mDrmManager->unloadPlugIns();
+ delete mDrmManager; mDrmManager = NULL;
+}
+
+int DrmManagerService::addUniqueId(int uniqueId) {
+ return mDrmManager->addUniqueId(uniqueId);
+}
+
+void DrmManagerService::removeUniqueId(int uniqueId) {
+ mDrmManager->removeUniqueId(uniqueId);
+}
+
+void DrmManagerService::addClient(int uniqueId) {
+ mDrmManager->addClient(uniqueId);
+}
+
+void DrmManagerService::removeClient(int uniqueId) {
+ mDrmManager->removeClient(uniqueId);
+}
+
+status_t DrmManagerService::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ LOGV("Entering setDrmServiceListener");
+ mDrmManager->setDrmServiceListener(uniqueId, drmServiceListener);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ LOGV("Entering installDrmEngine");
+ return mDrmManager->installDrmEngine(uniqueId, drmEngineFile);
+}
+
+DrmConstraints* DrmManagerService::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ LOGV("Entering getConstraints from content");
+ return mDrmManager->getConstraints(uniqueId, path, action);
+}
+
+DrmMetadata* DrmManagerService::getMetadata(int uniqueId, const String8* path) {
+ LOGV("Entering getMetadata from content");
+ return mDrmManager->getMetadata(uniqueId, path);
+}
+
+bool DrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Entering canHandle");
+ return mDrmManager->canHandle(uniqueId, path, mimeType);
+}
+
+DrmInfoStatus* DrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ LOGV("Entering processDrmInfo");
+ return mDrmManager->processDrmInfo(uniqueId, drmInfo);
+}
+
+DrmInfo* DrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ LOGV("Entering acquireDrmInfo");
+ return mDrmManager->acquireDrmInfo(uniqueId, drmInfoRequest);
+}
+
+status_t DrmManagerService::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ LOGV("Entering saveRights");
+ return mDrmManager->saveRights(uniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) {
+ LOGV("Entering getOriginalMimeType");
+ return mDrmManager->getOriginalMimeType(uniqueId, path);
+}
+
+int DrmManagerService::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Entering getDrmObjectType");
+ return mDrmManager->getDrmObjectType(uniqueId, path, mimeType);
+}
+
+int DrmManagerService::checkRightsStatus(
+ int uniqueId, const String8& path, int action) {
+ LOGV("Entering checkRightsStatus");
+ return mDrmManager->checkRightsStatus(uniqueId, path, action);
+}
+
+status_t DrmManagerService::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ LOGV("Entering consumeRights");
+ return mDrmManager->consumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+status_t DrmManagerService::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ LOGV("Entering setPlaybackStatus");
+ return mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmManagerService::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ LOGV("Entering validateAction");
+ return mDrmManager->validateAction(uniqueId, path, action, description);
+}
+
+status_t DrmManagerService::removeRights(int uniqueId, const String8& path) {
+ LOGV("Entering removeRights");
+ return mDrmManager->removeRights(uniqueId, path);
+}
+
+status_t DrmManagerService::removeAllRights(int uniqueId) {
+ LOGV("Entering removeAllRights");
+ return mDrmManager->removeAllRights(uniqueId);
+}
+
+int DrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
+ LOGV("Entering openConvertSession");
+ return mDrmManager->openConvertSession(uniqueId, mimeType);
+}
+
+DrmConvertedStatus* DrmManagerService::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ LOGV("Entering convertData");
+ return mDrmManager->convertData(uniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmManagerService::closeConvertSession(int uniqueId, int convertId) {
+ LOGV("Entering closeConvertSession");
+ return mDrmManager->closeConvertSession(uniqueId, convertId);
+}
+
+status_t DrmManagerService::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ LOGV("Entering getAllSupportInfo");
+ return mDrmManager->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+}
+
+DecryptHandle* DrmManagerService::openDecryptSession(
+ int uniqueId, int fd, int offset, int length) {
+ LOGV("Entering DrmManagerService::openDecryptSession");
+ if (isProtectedCallAllowed()) {
+ return mDrmManager->openDecryptSession(uniqueId, fd, offset, length);
+ }
+
+ return NULL;
+}
+
+DecryptHandle* DrmManagerService::openDecryptSession(
+ int uniqueId, const char* uri) {
+ LOGV("Entering DrmManagerService::openDecryptSession with uri");
+ if (isProtectedCallAllowed()) {
+ return mDrmManager->openDecryptSession(uniqueId, uri);
+ }
+
+ return NULL;
+}
+
+status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ LOGV("Entering closeDecryptSession");
+ return mDrmManager->closeDecryptSession(uniqueId, decryptHandle);
+}
+
+status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ LOGV("Entering initializeDecryptUnit");
+ return mDrmManager->initializeDecryptUnit(uniqueId,decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmManagerService::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ LOGV("Entering decrypt");
+ return mDrmManager->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+}
+
+status_t DrmManagerService::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ LOGV("Entering finalizeDecryptUnit");
+ return mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ LOGV("Entering pread");
+ return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/drmserver/StringTokenizer.cpp b/drm/drmserver/StringTokenizer.cpp
new file mode 100644
index 0000000..2130a00
--- /dev/null
+++ b/drm/drmserver/StringTokenizer.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "StringTokenizer.h"
+
+using namespace android;
+
+StringTokenizer::StringTokenizer(const String8& string, const String8& delimiter) {
+ splitString(string, delimiter);
+}
+
+void StringTokenizer::splitString(const String8& string, const String8& delimiter) {
+ for (unsigned int i = 0; i < string.length(); i++) {
+ unsigned int position = string.find(delimiter.string(), i);
+ if (string.length() != position) {
+ String8 token(string.string()+i, position-i);
+ if (token.length()) {
+ mStringTokenizerVector.push(token);
+ i = position + delimiter.length() - 1;
+ }
+ } else {
+ mStringTokenizerVector.push(String8(string.string()+i, string.length()-i));
+ break;
+ }
+ }
+}
+
+StringTokenizer::Iterator StringTokenizer::iterator() {
+ return Iterator(this);
+}
+
+StringTokenizer::Iterator::Iterator(const StringTokenizer::Iterator& iterator) :
+ mStringTokenizer(iterator.mStringTokenizer),
+ mIndex(iterator.mIndex) {
+}
+
+StringTokenizer::Iterator& StringTokenizer::Iterator::operator=(
+ const StringTokenizer::Iterator& iterator) {
+ mStringTokenizer = iterator.mStringTokenizer;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool StringTokenizer::Iterator::hasNext() {
+ return mIndex < mStringTokenizer->mStringTokenizerVector.size();
+}
+
+String8& StringTokenizer::Iterator::next() {
+ String8& value = mStringTokenizer->mStringTokenizerVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/drmserver/main_drmserver.cpp b/drm/drmserver/main_drmserver.cpp
new file mode 100644
index 0000000..6d10646
--- /dev/null
+++ b/drm/drmserver/main_drmserver.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <grp.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <private/android_filesystem_config.h>
+
+#include <DrmManagerService.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ LOGI("ServiceManager: %p", sm.get());
+ DrmManagerService::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+}
+
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
new file mode 100644
index 0000000..99133ba
--- /dev/null
+++ b/drm/libdrmframework/Android.mk
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DrmManagerClientImpl.cpp \
+ DrmManagerClient.cpp
+
+LOCAL_MODULE:= libdrmframework
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libbinder
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_STATIC_LIBRARIES := \
+ libdrmframeworkcommon
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/include
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
new file mode 100644
index 0000000..fa3d52a
--- /dev/null
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <utils/String8.h>
+#include <binder/IServiceManager.h>
+#include <drm/DrmManagerClient.h>
+
+#include "DrmManagerClientImpl.h"
+
+using namespace android;
+
+DrmManagerClient::DrmManagerClient():
+ mUniqueId(0), mDrmManagerClientImpl(NULL) {
+ mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId);
+ mDrmManagerClientImpl->addClient(mUniqueId);
+}
+
+DrmManagerClient::~DrmManagerClient() {
+ DrmManagerClientImpl::remove(mUniqueId);
+ mDrmManagerClientImpl->removeClient(mUniqueId);
+ delete mDrmManagerClientImpl; mDrmManagerClientImpl = NULL;
+}
+
+status_t DrmManagerClient::setOnInfoListener(
+ const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ return mDrmManagerClientImpl->setOnInfoListener(mUniqueId, infoListener);
+}
+
+DrmConstraints* DrmManagerClient::getConstraints(const String8* path, const int action) {
+ return mDrmManagerClientImpl->getConstraints(mUniqueId, path, action);
+}
+
+DrmMetadata* DrmManagerClient::getMetadata(const String8* path) {
+ return mDrmManagerClientImpl->getMetadata(mUniqueId, path);
+}
+
+bool DrmManagerClient::canHandle(const String8& path, const String8& mimeType) {
+ return mDrmManagerClientImpl->canHandle(mUniqueId, path, mimeType);
+}
+
+DrmInfoStatus* DrmManagerClient::processDrmInfo(const DrmInfo* drmInfo) {
+ return mDrmManagerClientImpl->processDrmInfo(mUniqueId, drmInfo);
+}
+
+DrmInfo* DrmManagerClient::acquireDrmInfo(const DrmInfoRequest* drmInfoRequest) {
+ return mDrmManagerClientImpl->acquireDrmInfo(mUniqueId, drmInfoRequest);
+}
+
+status_t DrmManagerClient::saveRights(
+ const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath) {
+ return mDrmManagerClientImpl->saveRights(mUniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerClient::getOriginalMimeType(const String8& path) {
+ return mDrmManagerClientImpl->getOriginalMimeType(mUniqueId, path);
+}
+
+int DrmManagerClient::getDrmObjectType(const String8& path, const String8& mimeType) {
+ return mDrmManagerClientImpl->getDrmObjectType( mUniqueId, path, mimeType);
+}
+
+int DrmManagerClient::checkRightsStatus(const String8& path, int action) {
+ return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action);
+}
+
+status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) {
+ Mutex::Autolock _l(mDecryptLock);
+ return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
+}
+
+status_t DrmManagerClient::setPlaybackStatus(
+ DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ return mDrmManagerClientImpl
+ ->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmManagerClient::validateAction(
+ const String8& path, int action, const ActionDescription& description) {
+ return mDrmManagerClientImpl->validateAction(mUniqueId, path, action, description);
+}
+
+status_t DrmManagerClient::removeRights(const String8& path) {
+ return mDrmManagerClientImpl->removeRights(mUniqueId, path);
+}
+
+status_t DrmManagerClient::removeAllRights() {
+ return mDrmManagerClientImpl->removeAllRights(mUniqueId);
+}
+
+int DrmManagerClient::openConvertSession(const String8& mimeType) {
+ return mDrmManagerClientImpl->openConvertSession(mUniqueId, mimeType);
+}
+
+DrmConvertedStatus* DrmManagerClient::convertData(int convertId, const DrmBuffer* inputData) {
+ return mDrmManagerClientImpl->convertData(mUniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmManagerClient::closeConvertSession(int convertId) {
+ return mDrmManagerClientImpl->closeConvertSession(mUniqueId, convertId);
+}
+
+status_t DrmManagerClient::getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray) {
+ return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray);
+}
+
+DecryptHandle* DrmManagerClient::openDecryptSession(int fd, int offset, int length) {
+ return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length);
+}
+
+DecryptHandle* DrmManagerClient::openDecryptSession(const char* uri) {
+ return mDrmManagerClientImpl->openDecryptSession(mUniqueId, uri);
+}
+
+status_t DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) {
+ return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
+}
+
+status_t DrmManagerClient::initializeDecryptUnit(
+ DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ Mutex::Autolock _l(mDecryptLock);
+ return mDrmManagerClientImpl->initializeDecryptUnit(
+ mUniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmManagerClient::decrypt(
+ DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ Mutex::Autolock _l(mDecryptLock);
+ return mDrmManagerClientImpl->decrypt(
+ mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+}
+
+status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) {
+ Mutex::Autolock _l(mDecryptLock);
+ return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmManagerClient::pread(
+ DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) {
+ Mutex::Autolock _l(mDecryptLock);
+ return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
new file mode 100644
index 0000000..32fa491
--- /dev/null
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2010 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 "DrmManagerClientImpl(Native)"
+#include <utils/Log.h>
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <binder/IServiceManager.h>
+
+#include "DrmManagerClientImpl.h"
+
+using namespace android;
+
+#define INVALID_VALUE -1
+
+Mutex DrmManagerClientImpl::mMutex;
+sp<IDrmManagerService> DrmManagerClientImpl::mDrmManagerService;
+const String8 DrmManagerClientImpl::EMPTY_STRING("");
+
+DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) {
+ if (0 == *pUniqueId) {
+ int uniqueId = getDrmManagerService()->addUniqueId(*pUniqueId);
+ *pUniqueId = uniqueId;
+ } else {
+ getDrmManagerService()->addUniqueId(*pUniqueId);
+ }
+ return new DrmManagerClientImpl();
+}
+
+void DrmManagerClientImpl::remove(int uniqueId) {
+ getDrmManagerService()->removeUniqueId(uniqueId);
+}
+
+const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
+ mMutex.lock();
+ if (NULL == mDrmManagerService.get()) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("drm.drmManager"));
+ if (binder != 0) {
+ break;
+ }
+ LOGW("DrmManagerService not published, waiting...");
+ struct timespec reqt;
+ reqt.tv_sec = 0;
+ reqt.tv_nsec = 500000000; //0.5 sec
+ nanosleep(&reqt, NULL);
+ } while (true);
+
+ mDrmManagerService = interface_cast<IDrmManagerService>(binder);
+ }
+ mMutex.unlock();
+ return mDrmManagerService;
+}
+
+void DrmManagerClientImpl::addClient(int uniqueId) {
+ getDrmManagerService()->addClient(uniqueId);
+}
+
+void DrmManagerClientImpl::removeClient(int uniqueId) {
+ getDrmManagerService()->removeClient(uniqueId);
+}
+
+status_t DrmManagerClientImpl::setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ Mutex::Autolock _l(mLock);
+ mOnInfoListener = infoListener;
+ return getDrmManagerService()->setDrmServiceListener(uniqueId, this);
+}
+
+status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != drmEngineFile) {
+ status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile);
+ }
+ return status;
+}
+
+DrmConstraints* DrmManagerClientImpl::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ DrmConstraints *drmConstraints = NULL;
+ if ((NULL != path) && (EMPTY_STRING != *path)) {
+ drmConstraints = getDrmManagerService()->getConstraints(uniqueId, path, action);
+ }
+ return drmConstraints;
+}
+
+DrmMetadata* DrmManagerClientImpl::getMetadata(int uniqueId, const String8* path) {
+ DrmMetadata *drmMetadata = NULL;
+ if ((NULL != path) && (EMPTY_STRING != *path)) {
+ drmMetadata = getDrmManagerService()->getMetadata(uniqueId, path);
+ }
+ return drmMetadata;
+}
+
+bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ bool retCode = false;
+ if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
+ retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType);
+ }
+ return retCode;
+}
+
+DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ DrmInfoStatus *drmInfoStatus = NULL;
+ if (NULL != drmInfo) {
+ drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo);
+ }
+ return drmInfoStatus;
+}
+
+DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ DrmInfo* drmInfo = NULL;
+ if (NULL != drmInfoRequest) {
+ drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest);
+ }
+ return drmInfo;
+}
+
+status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != contentPath) {
+ status = getDrmManagerService()->saveRights(uniqueId, drmRights, rightsPath, contentPath);
+ }
+ return status;
+}
+
+String8 DrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path) {
+ String8 mimeType = EMPTY_STRING;
+ if (EMPTY_STRING != path) {
+ mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path);
+ }
+ return mimeType;
+}
+
+int DrmManagerClientImpl::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ int drmOjectType = DrmObjectType::UNKNOWN;
+ if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
+ drmOjectType = getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
+ }
+ return drmOjectType;
+}
+
+int DrmManagerClientImpl::checkRightsStatus(
+ int uniqueId, const String8& path, int action) {
+ int rightsStatus = RightsStatus::RIGHTS_INVALID;
+ if (EMPTY_STRING != path) {
+ rightsStatus = getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
+ }
+ return rightsStatus;
+}
+
+status_t DrmManagerClientImpl::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle) {
+ status = getDrmManagerService()->consumeRights(uniqueId, decryptHandle, action, reserve);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle) {
+ status = getDrmManagerService()->setPlaybackStatus(
+ uniqueId, decryptHandle, playbackStatus, position);
+ }
+ return status;
+}
+
+bool DrmManagerClientImpl::validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ bool retCode = false;
+ if (EMPTY_STRING != path) {
+ retCode = getDrmManagerService()->validateAction(uniqueId, path, action, description);
+ }
+ return retCode;
+}
+
+status_t DrmManagerClientImpl::removeRights(int uniqueId, const String8& path) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != path) {
+ status = getDrmManagerService()->removeRights(uniqueId, path);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::removeAllRights(int uniqueId) {
+ return getDrmManagerService()->removeAllRights(uniqueId);
+}
+
+int DrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+ int retCode = INVALID_VALUE;
+ if (EMPTY_STRING != mimeType) {
+ retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType);
+ }
+ return retCode;
+}
+
+DrmConvertedStatus* DrmManagerClientImpl::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+ if (NULL != inputData) {
+ drmConvertedStatus = getDrmManagerService()->convertData(uniqueId, convertId, inputData);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+ return getDrmManagerService()->closeConvertSession(uniqueId, convertId);
+}
+
+status_t DrmManagerClientImpl::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != drmSupportInfoArray) && (NULL != length)) {
+ status = getDrmManagerService()->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+ }
+ return status;
+}
+
+DecryptHandle* DrmManagerClientImpl::openDecryptSession(
+ int uniqueId, int fd, int offset, int length) {
+ return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length);
+}
+
+DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char* uri) {
+ DecryptHandle* handle = NULL;
+ if (NULL != uri) {
+ handle = getDrmManagerService()->openDecryptSession(uniqueId, uri);
+ }
+ return handle;
+}
+
+status_t DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle) {
+ status = getDrmManagerService()->closeDecryptSession( uniqueId, decryptHandle);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != decryptHandle) && (NULL != headerInfo)) {
+ status = getDrmManagerService()->initializeDecryptUnit(
+ uniqueId, decryptHandle, decryptUnitId, headerInfo);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != decryptHandle) && (NULL != encBuffer)
+ && (NULL != decBuffer) && (NULL != *decBuffer)) {
+ status = getDrmManagerService()->decrypt(
+ uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle) {
+ status
+ = getDrmManagerService()->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+ }
+ return status;
+}
+
+ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ ssize_t retCode = INVALID_VALUE;
+ if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) {
+ retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+ }
+ return retCode;
+}
+
+status_t DrmManagerClientImpl::notify(const DrmInfoEvent& event) {
+ if (NULL != mOnInfoListener.get()) {
+ Mutex::Autolock _l(mLock);
+ sp<DrmManagerClient::OnInfoListener> listener = mOnInfoListener;
+ listener->onInfo(event);
+ }
+ return DRM_NO_ERROR;
+}
+
diff --git a/drm/libdrmframework/include/DrmIOService.h b/drm/libdrmframework/include/DrmIOService.h
new file mode 100644
index 0000000..244124e
--- /dev/null
+++ b/drm/libdrmframework/include/DrmIOService.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 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_IO_SERVICE_H__
+#define __DRM_IO_SERVICE_H__
+
+#include "IDrmIOService.h"
+
+namespace android {
+
+/**
+ * This is the implementation class for DRM IO service.
+ *
+ * The instance of this class is created while starting the DRM IO service.
+ *
+ */
+class DrmIOService : public BnDrmIOService {
+public:
+ static void instantiate();
+
+private:
+ DrmIOService();
+ virtual ~DrmIOService();
+
+public:
+ void writeToFile(const String8& filePath, const String8& dataBuffer);
+ String8 readFromFile(const String8& filePath);
+};
+
+};
+
+#endif /* __DRM_IO_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
new file mode 100644
index 0000000..bc462c2
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2010 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_MANAGER_H__
+#define __DRM_MANAGER_H__
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmEngine.h"
+#include "PlugInManager.h"
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class IDrmManager;
+class DrmRegistrationInfo;
+class DrmUnregistrationInfo;
+class DrmRightsAcquisitionInfo;
+class DrmContentIds;
+class DrmConstraints;
+class DrmMetadata;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmConvertedStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class ActionDescription;
+
+/**
+ * This is implementation class for DRM Manager. This class delegates the
+ * functionality to corresponding DRM Engine.
+ *
+ * The DrmManagerService class creates an instance of this class.
+ *
+ */
+class DrmManager : public IDrmEngine::OnInfoListener {
+public:
+ DrmManager();
+ virtual ~DrmManager();
+
+public:
+ int addUniqueId(int uniqueId);
+
+ void removeUniqueId(int uniqueId);
+
+ void addClient(int uniqueId);
+
+ void removeClient(int uniqueId);
+
+ status_t loadPlugIns();
+
+ status_t loadPlugIns(const String8& plugInDirPath);
+
+ status_t unloadPlugIns();
+
+ status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
+
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t removeRights(int uniqueId, const String8& path);
+
+ status_t removeAllRights(int uniqueId);
+
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+ void onInfo(const DrmInfoEvent& event);
+
+private:
+ String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
+
+ String8 getSupportedPlugInId(const String8& mimeType);
+
+ String8 getSupportedPlugInIdFromPath(int uniqueId, const String8& path);
+
+ bool canHandle(int uniqueId, const String8& path);
+
+private:
+ static Vector<int> mUniqueIdVector;
+ static const String8 EMPTY_STRING;
+
+ int mDecryptSessionId;
+ int mConvertId;
+ Mutex mLock;
+ Mutex mDecryptLock;
+ Mutex mConvertLock;
+ TPlugInManager<IDrmEngine> mPlugInManager;
+ KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
+ KeyedVector< int, IDrmEngine*> mConvertSessionMap;
+ KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
+ KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
+};
+
+};
+
+#endif /* __DRM_MANAGER_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
new file mode 100644
index 0000000..ff84fc7
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2010 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_MANAGER_CLIENT_IMPL_H__
+#define __DRM_MANAGER_CLIENT_IMPL_H__
+
+#include <binder/IMemory.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+#include "IDrmManagerService.h"
+
+namespace android {
+
+class DrmInfoEvent;
+/**
+ * This is implementation class for DrmManagerClient class.
+ *
+ * Only the JNI layer creates an instance of this class to delegate
+ * functionality to Native later.
+ *
+ */
+class DrmManagerClientImpl : public BnDrmServiceListener {
+private:
+ DrmManagerClientImpl() { }
+
+public:
+ static DrmManagerClientImpl* create(int* pUniqueId);
+
+ static void remove(int uniqueId);
+
+ virtual ~DrmManagerClientImpl() { }
+
+public:
+ /**
+ * Adds the client respective to given unique id.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ void addClient(int uniqueId);
+
+ /**
+ * Removes the client respective to given unique id.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ void removeClient(int uniqueId);
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener);
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ /**
+ * Get metadata information associated with input content.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ /**
+ * Check whether the given mimetype or path can be handled
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content needs to be handled
+ * @param[in] mimetype Mimetype of the content needs to be handled
+ * @return
+ * True if DrmManager can handle given path or mime type.
+ */
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path the path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ /**
+ * Informs the DRM engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeRights(int uniqueId, const String8& path);
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeAllRights(int uniqueId);
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] mimeType Description/MIME type of the input data packet
+ * @return Return handle for the convert session
+ */
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ /**
+ * Retrieves all DrmSupportInfo instance that native DRM framework can handle.
+ * This interface is meant to be used by JNI layer
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[out] length Number of elements in drmSupportInfoArray
+ * @param[out] drmSupportInfoArray Array contains all DrmSupportInfo
+ * that native DRM framework can handle
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * Handle for the decryption session
+ */
+ DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @return
+ * Handle for the decryption session
+ */
+ DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+ /**
+ * Notify the event to the registered listener
+ *
+ * @param[in] event The event to be notified
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t notify(const DrmInfoEvent& event);
+
+private:
+ /**
+ * Install new DRM Engine Plug-in at the runtime
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmEngine Shared Object(so) File in which DRM Engine defined
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+private:
+ Mutex mLock;
+ sp<DrmManagerClient::OnInfoListener> mOnInfoListener;
+
+private:
+ static Mutex mMutex;
+ static sp<IDrmManagerService> mDrmManagerService;
+ static const sp<IDrmManagerService>& getDrmManagerService();
+ static const String8 EMPTY_STRING;
+};
+
+};
+
+#endif /* __DRM_MANAGER_CLIENT_IMPL_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
new file mode 100644
index 0000000..f346356
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 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_MANAGER_SERVICE_H__
+#define __DRM_MANAGER_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include "IDrmManagerService.h"
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class DrmManager;
+class String8;
+class Mutex;
+
+/**
+ * This is the implementation class for DRM manager service. This delegates
+ * the responsibility to DrmManager.
+ *
+ * The instance of this class is created while starting the DRM manager service.
+ *
+ */
+class DrmManagerService : public BnDrmManagerService {
+public:
+ static void instantiate();
+
+private:
+ DrmManagerService();
+ virtual ~DrmManagerService();
+
+public:
+ int addUniqueId(int uniqueId);
+
+ void removeUniqueId(int uniqueId);
+
+ void addClient(int uniqueId);
+
+ void removeClient(int uniqueId);
+
+ status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
+
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest);
+
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path,int action);
+
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool validateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description);
+
+ status_t removeRights(int uniqueId, const String8& path);
+
+ status_t removeAllRights(int uniqueId);
+
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+private:
+ DrmManager* mDrmManager;
+};
+
+};
+
+#endif /* __DRM_MANAGER_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmIOService.h b/drm/libdrmframework/include/IDrmIOService.h
new file mode 100644
index 0000000..5e0d907
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmIOService.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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 __IDRM_IO_SERVICE_H__
+#define __IDRM_IO_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+/**
+ * This is the interface class for DRM IO service.
+ *
+ */
+class IDrmIOService : public IInterface
+{
+public:
+ enum {
+ WRITE_TO_FILE = IBinder::FIRST_CALL_TRANSACTION,
+ READ_FROM_FILE
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmIOService);
+
+public:
+ /**
+ * Writes the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to write
+ */
+ virtual void writeToFile(const String8& filePath, const String8& dataBuffer) = 0;
+
+ /**
+ * Reads the data from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @return Data read from the file
+ */
+ virtual String8 readFromFile(const String8& filePath) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM IO service.
+ */
+class BpDrmIOService: public BpInterface<IDrmIOService>
+{
+public:
+ BpDrmIOService(const sp<IBinder>& impl)
+ : BpInterface<IDrmIOService>(impl) {}
+
+ virtual void writeToFile(const String8& filePath, const String8& dataBuffer);
+
+ virtual String8 readFromFile(const String8& filePath);
+};
+
+/**
+ * This is the Binder implementation class for DRM IO service.
+ */
+class BnDrmIOService: public BnInterface<IDrmIOService>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_IO_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
new file mode 100644
index 0000000..f1dabd3
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2010 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 __IDRM_MANAGER_SERVICE_H__
+#define __IDRM_MANAGER_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class DrmContentIds;
+class DrmConstraints;
+class DrmMetadata;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmConvertedStatus;
+class String8;
+class ActionDescription;
+
+/**
+ * This is the interface class for DRM Manager service.
+ *
+ */
+class IDrmManagerService : public IInterface
+{
+public:
+ enum {
+ ADD_UNIQUEID = IBinder::FIRST_CALL_TRANSACTION,
+ REMOVE_UNIQUEID,
+ ADD_CLIENT,
+ REMOVE_CLIENT,
+ SET_DRM_SERVICE_LISTENER,
+ INSTALL_DRM_ENGINE,
+ GET_CONSTRAINTS_FROM_CONTENT,
+ GET_METADATA_FROM_CONTENT,
+ CAN_HANDLE,
+ PROCESS_DRM_INFO,
+ ACQUIRE_DRM_INFO,
+ SAVE_RIGHTS,
+ GET_ORIGINAL_MIMETYPE,
+ GET_DRM_OBJECT_TYPE,
+ CHECK_RIGHTS_STATUS,
+ CONSUME_RIGHTS,
+ SET_PLAYBACK_STATUS,
+ VALIDATE_ACTION,
+ REMOVE_RIGHTS,
+ REMOVE_ALL_RIGHTS,
+ OPEN_CONVERT_SESSION,
+ CONVERT_DATA,
+ CLOSE_CONVERT_SESSION,
+ GET_ALL_SUPPORT_INFO,
+ OPEN_DECRYPT_SESSION,
+ OPEN_DECRYPT_SESSION_FROM_URI,
+ CLOSE_DECRYPT_SESSION,
+ INITIALIZE_DECRYPT_UNIT,
+ DECRYPT,
+ FINALIZE_DECRYPT_UNIT,
+ PREAD
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmManagerService);
+
+public:
+ virtual int addUniqueId(int uniqueId) = 0;
+
+ virtual void removeUniqueId(int uniqueId) = 0;
+
+ virtual void addClient(int uniqueId) = 0;
+
+ virtual void removeClient(int uniqueId) = 0;
+
+ virtual status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& infoListener) = 0;
+
+ virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile) = 0;
+
+ virtual DrmConstraints* getConstraints(
+ int uniqueId, const String8* path, const int action) = 0;
+
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path) = 0;
+
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) = 0;
+
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) = 0;
+
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ virtual int getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ virtual status_t consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0;
+
+ virtual status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) = 0;
+
+ virtual bool validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ virtual status_t removeRights(int uniqueId, const String8& path) = 0;
+
+ virtual status_t removeAllRights(int uniqueId) = 0;
+
+ virtual int openConvertSession(int uniqueId, const String8& mimeType) = 0;
+
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId) = 0;
+
+ virtual status_t getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) = 0;
+
+ virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length) = 0;
+
+ virtual DecryptHandle* openDecryptSession(int uniqueId, const char* uri) = 0;
+
+ virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0;
+
+ virtual status_t finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes,off_t offset) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM Manager service.
+ */
+class BpDrmManagerService: public BpInterface<IDrmManagerService>
+{
+public:
+ BpDrmManagerService(const sp<IBinder>& impl)
+ : BpInterface<IDrmManagerService>(impl) {}
+
+ virtual int addUniqueId(int uniqueId);
+
+ virtual void removeUniqueId(int uniqueId);
+
+ virtual void addClient(int uniqueId);
+
+ virtual void removeClient(int uniqueId);
+
+ virtual status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& infoListener);
+
+ virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ virtual DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest);
+
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ virtual int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ virtual status_t consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ virtual status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ virtual bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ virtual status_t removeRights(int uniqueId, const String8& path);
+
+ virtual status_t removeAllRights(int uniqueId);
+
+ virtual int openConvertSession(int uniqueId, const String8& mimeType);
+
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ virtual status_t getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ virtual DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
+ virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ virtual status_t finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+};
+
+/**
+ * This is the Binder implementation class for DRM Manager service.
+ */
+class BnDrmManagerService: public BnInterface<IDrmManagerService>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_MANAGER_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmServiceListener.h b/drm/libdrmframework/include/IDrmServiceListener.h
new file mode 100644
index 0000000..7f7109f
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmServiceListener.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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 __IDRM_SERVICE_LISTENER_H__
+#define __IDRM_SERVICE_LISTENER_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class DrmInfoEvent;
+
+/**
+ * This is the interface class for DRM service listener.
+ *
+ */
+class IDrmServiceListener : public IInterface
+{
+public:
+ enum {
+ NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmServiceListener);
+
+public:
+ virtual status_t notify(const DrmInfoEvent& event) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM service listener.
+ */
+class BpDrmServiceListener: public BpInterface<IDrmServiceListener>
+{
+public:
+ BpDrmServiceListener(const sp<IBinder>& impl)
+ : BpInterface<IDrmServiceListener>(impl) {}
+
+ virtual status_t notify(const DrmInfoEvent& event);
+};
+
+/**
+ * This is the Binder implementation class for DRM service listener.
+ */
+class BnDrmServiceListener: public BnInterface<IDrmServiceListener>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_SERVICE_LISTENER_H__ */
+
diff --git a/drm/libdrmframework/include/PlugInManager.h b/drm/libdrmframework/include/PlugInManager.h
new file mode 100644
index 0000000..9ad195f
--- /dev/null
+++ b/drm/libdrmframework/include/PlugInManager.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 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 __PLUGIN_MANAGER_H__
+#define __PLUGIN_MANAGER_H__
+
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+const char* const PLUGIN_MANAGER_CREATE = "create";
+const char* const PLUGIN_MANAGER_DESTROY = "destroy";
+const char* const PLUGIN_EXTENSION = ".so";
+
+/**
+ * This is the template class for Plugin manager.
+ *
+ * The DrmManager uses this class to handle the plugins.
+ *
+ */
+template<typename Type>
+class TPlugInManager {
+private:
+ typedef void* HANDLE;
+ typedef Type* create_t(void);
+ typedef void destroy_t(Type*);
+ typedef create_t* FPCREATE;
+ typedef destroy_t* FPDESTORY;
+
+ typedef struct _PlugInContainer {
+ String8 sPath;
+ HANDLE hHandle;
+ FPCREATE fpCreate;
+ FPDESTORY fpDestory;
+ Type* pInstance;
+
+ _PlugInContainer():
+ sPath("")
+ ,hHandle(NULL)
+ ,fpCreate(NULL)
+ ,fpDestory(NULL)
+ ,pInstance(NULL)
+ {}
+ } PlugInContainer;
+
+ typedef KeyedVector<String8, PlugInContainer*> PlugInMap;
+ PlugInMap m_plugInMap;
+
+ typedef Vector<String8> PlugInIdList;
+ PlugInIdList m_plugInIdList;
+
+public:
+ /**
+ * Load all the plug-ins in the specified directory
+ *
+ * @param[in] rsPlugInDirPath
+ * Directory path which plug-ins (dynamic library) are stored
+ * @note Plug-ins should be implemented according to the specification
+ */
+ void loadPlugIns(const String8& rsPlugInDirPath) {
+ Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);
+
+ if (!plugInFileList.isEmpty()) {
+ for (unsigned int i = 0; i < plugInFileList.size(); ++i) {
+ loadPlugIn(plugInFileList[i]);
+ }
+ }
+ }
+
+ /**
+ * Unload all the plug-ins
+ *
+ */
+ void unloadPlugIns() {
+ for (unsigned int i = 0; i < m_plugInIdList.size(); ++i) {
+ unloadPlugIn(m_plugInIdList[i]);
+ }
+ m_plugInIdList.clear();
+ }
+
+ /**
+ * Get all the IDs of available plug-ins
+ *
+ * @return[in] plugInIdList
+ * String type Vector in which all plug-in IDs are stored
+ */
+ Vector<String8> getPlugInIdList() const {
+ return m_plugInIdList;
+ }
+
+ /**
+ * Get a plug-in reference of specified ID
+ *
+ * @param[in] rsPlugInId
+ * Plug-in ID to be used
+ * @return plugIn
+ * Reference of specified plug-in instance
+ */
+ Type& getPlugIn(const String8& rsPlugInId) {
+ if (!contains(rsPlugInId)) {
+ // This error case never happens
+ }
+ return *(m_plugInMap.valueFor(rsPlugInId)->pInstance);
+ }
+
+public:
+ /**
+ * Load a plug-in stored in the specified path
+ *
+ * @param[in] rsPlugInPath
+ * Plug-in (dynamic library) file path
+ * @note Plug-in should be implemented according to the specification
+ */
+ void loadPlugIn(const String8& rsPlugInPath) {
+ if (contains(rsPlugInPath)) {
+ return;
+ }
+
+ PlugInContainer* pPlugInContainer = new PlugInContainer();
+
+ pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);
+
+ if (NULL == pPlugInContainer->hHandle) {
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ return;
+ }
+
+ pPlugInContainer->sPath = rsPlugInPath;
+ pPlugInContainer->fpCreate
+ = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE);
+ pPlugInContainer->fpDestory
+ = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY);
+
+ if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) {
+ pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate();
+ m_plugInIdList.add(rsPlugInPath);
+ m_plugInMap.add(rsPlugInPath, pPlugInContainer);
+ } else {
+ dlclose(pPlugInContainer->hHandle);
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ return;
+ }
+ }
+
+ /**
+ * Unload a plug-in stored in the specified path
+ *
+ * @param[in] rsPlugInPath
+ * Plug-in (dynamic library) file path
+ */
+ void unloadPlugIn(const String8& rsPlugInPath) {
+ if (!contains(rsPlugInPath)) {
+ return;
+ }
+
+ PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath);
+ pPlugInContainer->fpDestory(pPlugInContainer->pInstance);
+ dlclose(pPlugInContainer->hHandle);
+
+ m_plugInMap.removeItem(rsPlugInPath);
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ }
+
+private:
+ /**
+ * True if TPlugInManager contains rsPlugInId
+ */
+ bool contains(const String8& rsPlugInId) {
+ return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND;
+ }
+
+ /**
+ * Return file path list of plug-ins stored in the specified directory
+ *
+ * @param[in] rsDirPath
+ * Directory path in which plug-ins are stored
+ * @return plugInFileList
+ * String type Vector in which file path of plug-ins are stored
+ */
+ Vector<String8> getPlugInPathList(const String8& rsDirPath) {
+ Vector<String8> fileList;
+ DIR* pDir = opendir(rsDirPath.string());
+ struct dirent* pEntry = new dirent();
+
+ while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
+ if (!isPlugIn(pEntry)) {
+ continue;
+ }
+ String8 plugInPath;
+ plugInPath += rsDirPath;
+ plugInPath += "/";
+ plugInPath += pEntry->d_name;
+
+ fileList.add(plugInPath);
+ }
+
+ if (NULL != pDir) {
+ closedir(pDir);
+ }
+ delete pEntry;
+ pEntry = NULL;
+
+ return fileList;
+ }
+
+ /**
+ * True if the input name denotes plug-in
+ */
+ bool isPlugIn(const struct dirent* pEntry) const {
+ String8 sName(pEntry->d_name);
+ int extentionPos = sName.size() - String8(PLUGIN_EXTENSION).size();
+ if (extentionPos < 0) {
+ return false;
+ }
+ return extentionPos == (int)sName.find(PLUGIN_EXTENSION);
+ }
+
+ /**
+ * True if the input entry is "." or ".."
+ */
+ bool isDotOrDDot(const struct dirent* pEntry) const {
+ String8 sName(pEntry->d_name);
+ return "." == sName || ".." == sName;
+ }
+
+ /**
+ * True if input entry is directory
+ */
+ bool isDirectory(const struct dirent* pEntry) const {
+ return DT_DIR == pEntry->d_type;
+ }
+
+ /**
+ * True if input entry is regular file
+ */
+ bool isRegularFile(const struct dirent* pEntry) const {
+ return DT_REG == pEntry->d_type;
+ }
+
+ /**
+ * True if input entry is link
+ */
+ bool isLink(const struct dirent* pEntry) const {
+ return DT_LNK == pEntry->d_type;
+ }
+};
+
+};
+
+#endif /* __PLUGIN_MANAGER_H__ */
+
diff --git a/drm/libdrmframework/include/ReadWriteUtils.h b/drm/libdrmframework/include/ReadWriteUtils.h
new file mode 100644
index 0000000..529b342
--- /dev/null
+++ b/drm/libdrmframework/include/ReadWriteUtils.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 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 __READ_WRITE_UTILS_H__
+#define __READ_WRITE_UTILS_H__
+
+#include <utils/FileMap.h>
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+/**
+ * This is an utility class which performs IO operations.
+ *
+ */
+class ReadWriteUtils {
+public:
+ /**
+ * Constructor for ReadWriteUtils
+ */
+ ReadWriteUtils() {}
+
+ /**
+ * Destructor for ReadWriteUtils
+ */
+ virtual ~ReadWriteUtils();
+
+public:
+ /**
+ * Reads the data from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @return Data read from the file
+ */
+ static String8 readBytes(const String8& filePath);
+ /**
+ * Reads the data into the given buffer from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[out] buffer Data read from the file
+ * @return Length of the data read from the file
+ */
+ static int readBytes(const String8& filePath, char** buffer);
+ /**
+ * Writes the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to write
+ */
+ static void writeToFile(const String8& filePath, const String8& data);
+ /**
+ * Appends the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to append
+ */
+ static void appendToFile(const String8& filePath, const String8& data);
+
+private:
+ FileMap* mFileMap;
+};
+
+};
+
+#endif /* __READ_WRITE_UTILS_H__ */
+
diff --git a/drm/libdrmframework/include/StringTokenizer.h b/drm/libdrmframework/include/StringTokenizer.h
new file mode 100644
index 0000000..70e7558
--- /dev/null
+++ b/drm/libdrmframework/include/StringTokenizer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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 __STRING_TOKENIZER_H__
+#define __STRING_TOKENIZER_H__
+
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+/**
+ * This is an utility class for String manipulation.
+ *
+ */
+class StringTokenizer {
+public:
+ /**
+ * Iterator for string tokens
+ */
+ class Iterator {
+ friend class StringTokenizer;
+ private:
+ Iterator(StringTokenizer* StringTokenizer)
+ : mStringTokenizer(StringTokenizer), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ StringTokenizer* mStringTokenizer;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Constructor for StringTokenizer
+ *
+ * @param[in] string Complete string data
+ * @param[in] delimeter Delimeter used to split the string
+ */
+ StringTokenizer(const String8& string, const String8& delimeter);
+
+ /**
+ * Destructor for StringTokenizer
+ */
+ ~StringTokenizer() {}
+
+private:
+ /**
+ * Splits the string according to the delimeter
+ */
+ void splitString(const String8& string, const String8& delimeter);
+
+public:
+ /**
+ * Returns Iterator object to walk through the split string values
+ *
+ * @return Iterator object
+ */
+ Iterator iterator();
+
+private:
+ Vector<String8> mStringTokenizerVector;
+};
+
+};
+#endif /* __STRING_TOKENIZER_H__ */
+
diff --git a/drm/libdrmframework/plugins/Android.mk b/drm/libdrmframework/plugins/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/Android.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2010 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.
+#
+include $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
new file mode 100644
index 0000000..67b6355
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2010 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_ENGINE_BASE_H__
+#define __DRM_ENGINE_BASE_H__
+
+#include <drm/drm_framework_common.h>
+#include "IDrmEngine.h"
+
+namespace android {
+
+/**
+ * This class is an interface for plug-in developers
+ *
+ * Responsibility of this class is control the sequence of actual plug-in.
+ * All each plug-in developer has to do is implement onXXX() type virtual interfaces.
+ */
+class DrmEngineBase : public IDrmEngine {
+public:
+ DrmEngineBase();
+ virtual ~DrmEngineBase();
+
+public:
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, int action);
+
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ status_t initialize(int uniqueId);
+
+ status_t setOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t terminate(int uniqueId);
+
+ bool canHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t removeRights(int uniqueId, const String8& path);
+
+ status_t removeAllRights(int uniqueId);
+
+ status_t openConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* getSupportInfo(int uniqueId);
+
+ status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length);
+
+ status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri);
+
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+protected:
+ /////////////////////////////////////////////////////
+ // Interface for plug-in developers //
+ // each plug-in has to implement following method //
+ /////////////////////////////////////////////////////
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmConstraints* onGetConstraints(
+ int uniqueId, const String8* path, int action) = 0;
+
+ /**
+ * Get metadata information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmMetadata* onGetMetadata(int uniqueId, const String8* path) = 0;
+
+ /**
+ * Initialize plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onInitialize(int uniqueId) = 0;
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) = 0;
+
+ /**
+ * Terminate the plug-in
+ * and release resource bound to plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onTerminate(int uniqueId) = 0;
+
+ /**
+ * Get whether the given content can be handled by this plugin or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path the protected object
+ * @return bool
+ * Returns true if this plugin can handle , false in case of not able to handle
+ */
+ virtual bool onCanHandle(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ virtual DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightspath, const String8& contentPath) = 0;
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ virtual DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) = 0;
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ virtual String8 onGetOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ virtual int onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ virtual int onCheckRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) = 0;
+
+ /**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) = 0;
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ virtual bool onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onRemoveRights(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onRemoveAllRights(int uniqueId) = 0;
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onOpenConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ virtual DrmConvertedStatus* onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ virtual DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+ virtual DrmSupportInfo* onGetSupportInfo(int uniqueId) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri) = 0;
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptId Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptId Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ virtual status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0;
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ virtual ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) = 0;
+};
+
+};
+
+#endif /* __DRM_ENGINE_BASE_H__ */
+
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
new file mode 100644
index 0000000..f839070
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2010 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 __IDRM_ENGINE_H__
+#define __IDRM_ENGINE_H__
+
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+class DrmContentIds;
+class DrmConstraints;
+class DrmMetadata;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmConvertedStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmInfoEvent;
+
+/**
+ * This class is an interface for plug-in user
+ *
+ * Responsibility of this class is provide generic interface to DRM Engine Manager.
+ * Each interface need to be as abstract as possible.
+ */
+class IDrmEngine {
+public:
+ virtual ~IDrmEngine() {
+ }
+
+public:
+ class OnInfoListener {
+
+ public:
+ virtual void onInfo(const DrmInfoEvent& event) = 0;
+
+ virtual ~OnInfoListener() { }
+ };
+
+public:
+
+ //////////////////////////////////
+ // Implementation of IDrmEngine //
+ //////////////////////////////////
+
+ /**
+ * Initialize plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t initialize(int uniqueId) = 0;
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t setOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) = 0;
+
+ /**
+ * Terminate the plug-in
+ * and release resource bound to plug-in
+ * e.g.) release native resource
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t terminate(int uniqueId) = 0;
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmConstraints* getConstraints(
+ int uniqueId, const String8* path, int action) = 0;
+
+ /**
+ * Get metadata information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path) = 0;
+
+ /**
+ * Get whether the given content can be handled by this plugin or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path the protected object
+ * @return bool
+ * true if this plugin can handle , false in case of not able to handle
+ */
+ virtual bool canHandle(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) = 0;
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) = 0;
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ virtual int getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0;
+
+ /**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t setPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int position) = 0;
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ virtual bool validateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t removeRights(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t removeAllRights(int uniqueId) = 0;
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t openConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ virtual DrmConvertedStatus* closeConvertSession( int uniqueId, int convertId) = 0;
+
+ /**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+ virtual DrmSupportInfo* getSupportInfo(int uniqueId) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri) = 0;
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0;
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) = 0;
+};
+
+};
+
+#endif /* __IDRM_ENGINE_H__ */
+
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
new file mode 100644
index 0000000..7856d37
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ src/DrmPassthruPlugIn.cpp
+
+LOCAL_MODULE := libdrmpassthruplugin
+
+LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/passthru/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include \
+ $(TOP)/frameworks/base/include
+
+# Set the following flag to enable the decryption passthru flow
+#LOCAL_CFLAGS += -DENABLE_PASSTHRU_DECRYPTION
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
new file mode 100644
index 0000000..bbcd9ed
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2010 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_PASSTHRU_PLUGIN_H__
+#define __DRM_PASSTHRU_PLUGIN_H__
+
+#include <DrmEngineBase.h>
+
+namespace android {
+
+class DrmPassthruPlugIn : public DrmEngineBase {
+
+public:
+ DrmPassthruPlugIn();
+ virtual ~DrmPassthruPlugIn();
+
+protected:
+ DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
+
+ DrmMetadata* onGetMetadata(int uniqueId, const String8* path);
+
+ status_t onInitialize(int uniqueId);
+
+ status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t onTerminate(int uniqueId);
+
+ bool onCanHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ status_t onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 onGetOriginalMimeType(int uniqueId, const String8& path);
+
+ int onGetDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int onCheckRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool onValidateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t onRemoveRights(int uniqueId, const String8& path);
+
+ status_t onRemoveAllRights(int uniqueId);
+
+ status_t onOpenConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* onConvertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* onGetSupportInfo(int uniqueId);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri);
+
+ status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+private:
+ DecryptHandle* openDecryptSessionImpl();
+};
+
+};
+
+#endif /* __DRM_PASSTHRU_PLUGIN_H__ */
+
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
new file mode 100644
index 0000000..dee1fdb
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2010 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 "DrmPassthruPlugIn"
+#include <utils/Log.h>
+
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <DrmPassthruPlugIn.h>
+
+using namespace android;
+
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" IDrmEngine* create() {
+ return new DrmPassthruPlugIn();
+}
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" void destroy(IDrmEngine* pPlugIn) {
+ delete pPlugIn;
+ pPlugIn = NULL;
+}
+
+DrmPassthruPlugIn::DrmPassthruPlugIn()
+ : DrmEngineBase() {
+
+}
+
+DrmPassthruPlugIn::~DrmPassthruPlugIn() {
+
+}
+
+DrmMetadata* DrmPassthruPlugIn::onGetMetadata(int uniqueId, const String8* path) {
+ return NULL;
+}
+
+DrmConstraints* DrmPassthruPlugIn::onGetConstraints(
+ int uniqueId, const String8* path, int action) {
+ LOGD("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId);
+ DrmConstraints* drmConstraints = new DrmConstraints();
+
+ String8 value("dummy_available_time");
+ char* charValue = NULL;
+ charValue = new char[value.length() + 1];
+ strncpy(charValue, value.string(), value.length());
+
+ //Just add dummy available time for verification
+ drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue);
+
+ return drmConstraints;
+}
+
+DrmInfoStatus* DrmPassthruPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ LOGD("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId);
+ DrmInfoStatus* drmInfoStatus = NULL;
+ if (NULL != drmInfo) {
+ switch (drmInfo->getInfoType()) {
+ case DrmInfoRequest::TYPE_REGISTRATION_INFO: {
+ const DrmBuffer* emptyBuffer = new DrmBuffer();
+ drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+ DrmInfoRequest::TYPE_REGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType());
+ break;
+ }
+ case DrmInfoRequest::TYPE_UNREGISTRATION_INFO: {
+ const DrmBuffer* emptyBuffer = new DrmBuffer();
+ drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+ DrmInfoRequest::TYPE_UNREGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType());
+ break;
+ }
+ case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: {
+ String8 licenseString("dummy_license_string");
+ const int bufferSize = licenseString.size();
+ char* data = NULL;
+ data = new char[bufferSize];
+ memcpy(data, licenseString.string(), bufferSize);
+ const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
+ drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+ DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType());
+ break;
+ }
+ }
+ }
+ LOGD("DrmPassthruPlugIn::onProcessDrmInfo - Exit");
+ return drmInfoStatus;
+}
+
+status_t DrmPassthruPlugIn::onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ LOGD("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onInitialize(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onTerminate(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmSupportInfo* DrmPassthruPlugIn::onGetSupportInfo(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId);
+ DrmSupportInfo* drmSupportInfo = new DrmSupportInfo();
+ // Add mimetype's
+ drmSupportInfo->addMimeType(String8("application/vnd.passthru.drm"));
+ // Add File Suffixes
+ drmSupportInfo->addFileSuffix(String8(".passthru"));
+ // Add plug-in description
+ drmSupportInfo->setDescription(String8("Passthru plug-in"));
+ return drmSupportInfo;
+}
+
+status_t DrmPassthruPlugIn::onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ LOGD("DrmPassthruPlugIn::onSaveRights : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmInfo* DrmPassthruPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ LOGD("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId);
+ DrmInfo* drmInfo = NULL;
+
+ if (NULL != drmInfoRequest) {
+ String8 dataString("dummy_acquistion_string");
+ int length = dataString.length();
+ char* data = NULL;
+ data = new char[length];
+ memcpy(data, dataString.string(), length);
+ drmInfo = new DrmInfo(drmInfoRequest->getInfoType(),
+ DrmBuffer(data, length), drmInfoRequest->getMimeType());
+ }
+ return drmInfo;
+}
+
+bool DrmPassthruPlugIn::onCanHandle(int uniqueId, const String8& path) {
+ LOGD("DrmPassthruPlugIn::canHandle: %s ", path.string());
+ String8 extension = path.getPathExtension();
+ extension.toLower();
+ return (String8(".passthru") == extension);
+}
+
+String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path) {
+ LOGD("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
+ return String8("video/passthru");
+}
+
+int DrmPassthruPlugIn::onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ LOGD("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
+ return DrmObjectType::UNKNOWN;
+}
+
+int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
+ LOGD("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId);
+ int rightsStatus = RightsStatus::RIGHTS_VALID;
+ return rightsStatus;
+}
+
+status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) {
+ LOGD("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int position) {
+ LOGD("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+bool DrmPassthruPlugIn::onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ LOGD("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
+ return true;
+}
+
+status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& path) {
+ LOGD("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
+ LOGD("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmConvertedStatus* DrmPassthruPlugIn::onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ LOGD("DrmPassthruPlugIn::onConvertData() : %d", uniqueId);
+ DrmBuffer* convertedData = NULL;
+
+ if (NULL != inputData && 0 < inputData->length) {
+ int length = inputData->length;
+ char* data = NULL;
+ data = new char[length];
+ convertedData = new DrmBuffer(data, length);
+ memcpy(convertedData->data, inputData->data, length);
+ }
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, convertedData, 0 /*offset*/);
+}
+
+DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
+ LOGD("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/);
+}
+
+status_t DrmPassthruPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) {
+ LOGD("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId);
+
+#ifdef ENABLE_PASSTHRU_DECRYPTION
+ decryptHandle->mimeType = String8("video/passthru");
+ decryptHandle->decryptApiType = DecryptApiType::ELEMENTARY_STREAM_BASED;
+ decryptHandle->status = DRM_NO_ERROR;
+ decryptHandle->decryptInfo = NULL;
+ return DRM_NO_ERROR;
+#endif
+
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+status_t DrmPassthruPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ LOGD("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
+ if (NULL != decryptHandle) {
+ if (NULL != decryptHandle->decryptInfo) {
+ delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
+ }
+ delete decryptHandle; decryptHandle = NULL;
+ }
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ LOGD("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ LOGD("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId);
+ /**
+ * As a workaround implementation passthru would copy the given
+ * encrypted buffer as it is to decrypted buffer. Note, decBuffer
+ * memory has to be allocated by the caller.
+ */
+ if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) {
+ memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length);
+ (*decBuffer)->length = encBuffer->length;
+ }
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ LOGD("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ LOGD("DrmPassthruPlugIn::onPread() : %d", uniqueId);
+ return 0;
+}
+
diff --git a/include/drm/DrmConstraints.h b/include/drm/DrmConstraints.h
new file mode 100644
index 0000000..a9ec942
--- /dev/null
+++ b/include/drm/DrmConstraints.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2010 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_CONSTRAINTS_H__
+#define __DRM_CONSTRAINTS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which contains the constraints information.
+ *
+ * As a result of DrmManagerClient::getConstraints(const String8*, const int)
+ * an instance of DrmConstraints would be returned.
+ *
+ */
+class DrmConstraints {
+public:
+ /**
+ * The following variables are replica of android.drm.DrmStore.ConstraintsColumns
+ * Any changes should also be incorporated with Java Layer as well
+ */
+ /**
+ * The max repeat count
+ */
+ static const String8 MAX_REPEAT_COUNT;
+ /**
+ * The remaining repeat count
+ */
+ static const String8 REMAINING_REPEAT_COUNT;
+
+ /**
+ * The time before which the protected file can not be played/viewed
+ */
+ static const String8 LICENSE_START_TIME;
+
+ /**
+ * The time after which the protected file can not be played/viewed
+ */
+ static const String8 LICENSE_EXPIRY_TIME;
+
+ /**
+ * The available time for license
+ */
+ static const String8 LICENSE_AVAILABLE_TIME;
+
+ /**
+ * The data stream for extended metadata
+ */
+ static const String8 EXTENDED_METADATA;
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmConstraints;
+ private:
+ KeyIterator(DrmConstraints* drmConstraints)
+ : mDrmConstraints(drmConstraints), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmConstraints* mDrmConstraints;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for constraints
+ */
+ class Iterator {
+ friend class DrmConstraints;
+ private:
+ Iterator(DrmConstraints* drmConstraints)
+ : mDrmConstraints(drmConstraints), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8 next();
+
+ private:
+ DrmConstraints* mDrmConstraints;
+ unsigned int mIndex;
+ };
+
+public:
+ DrmConstraints() {}
+ virtual ~DrmConstraints() {
+ DrmConstraints::KeyIterator keyIt = this->keyIterator();
+
+ while (keyIt.hasNext()) {
+ String8 key = keyIt.next();
+ const char* value = this->getAsByteArray(&key);
+ if (NULL != value) {
+ delete[] value;
+ value = NULL;
+ }
+ }
+ mConstraintMap.clear();
+ }
+public:
+ /**
+ * Returns the number of constraints contained in this instance
+ *
+ * @return Number of constraints
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds constraint information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t put(const String8* key, const char* value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Retrieves the value as byte array of given key
+ * @param key Key whose value to be retrieved as byte array
+ * @return The byte array value
+ */
+ const char* getAsByteArray(const String8* key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator();
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator();
+private:
+ const char* getValue(const String8* key) const;
+private:
+ typedef KeyedVector<String8, const char*> DrmConstraintsMap;
+ DrmConstraintsMap mConstraintMap;
+};
+
+};
+
+#endif /* __DRM_CONSTRAINTS_H__ */
+
diff --git a/include/drm/DrmConvertedStatus.h b/include/drm/DrmConvertedStatus.h
new file mode 100644
index 0000000..679e48d
--- /dev/null
+++ b/include/drm/DrmConvertedStatus.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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_CONVERTED_STATUS_H__
+#define __DRM_CONVERTED_STATUS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the status of the conversion, the converted
+ * data/checksum data and the offset. Offset is going to be used in the case of close
+ * session where the agent will inform where the header and body signature should be added
+ *
+ * As a result of DrmManagerClient::convertData(int, const DrmBuffer*) and
+ * DrmManagerClient::closeConvertSession(int) an instance of DrmConvertedStatus
+ * would be returned.
+ *
+ */
+class DrmConvertedStatus {
+public:
+ // Should be in sync with DrmConvertedStatus.java
+ static const int STATUS_OK = 1;
+ static const int STATUS_INPUTDATA_ERROR = 2;
+ static const int STATUS_ERROR = 3;
+
+public:
+ /**
+ * Constructor for DrmConvertedStatus
+ *
+ * @param[in] _statusCode Status of the conversion
+ * @param[in] _convertedData Converted data/checksum data
+ * @param[in] _offset Offset value
+ */
+ DrmConvertedStatus(int _statusCode, const DrmBuffer* _convertedData, int _offset);
+
+ /**
+ * Destructor for DrmConvertedStatus
+ */
+ virtual ~DrmConvertedStatus() {
+
+ }
+
+public:
+ int statusCode;
+ const DrmBuffer* convertedData;
+ int offset;
+};
+
+};
+
+#endif /* __DRM_CONVERTED_STATUS_H__ */
+
diff --git a/include/drm/DrmInfo.h b/include/drm/DrmInfo.h
new file mode 100644
index 0000000..7b48541
--- /dev/null
+++ b/include/drm/DrmInfo.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 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_INFO_H__
+#define __DRM_INFO_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class in which necessary information required to transact
+ * between device and online DRM server is described. DRM Framework achieves
+ * server registration, license acquisition and any other server related transaction
+ * by passing an instance of this class to DrmManagerClient::processDrmInfo(const DrmInfo*).
+ *
+ * The Caller can retrieve the DrmInfo instance by using
+ * DrmManagerClient::acquireDrmInfo(const DrmInfoRequest*) by passing DrmInfoRequest instance.
+ *
+ */
+class DrmInfo {
+public:
+ /**
+ * Constructor for DrmInfo
+ *
+ * @param[in] infoType Type of information
+ * @param[in] drmBuffer Trigger data
+ * @param[in] mimeType MIME type
+ */
+ DrmInfo(int infoType, const DrmBuffer& drmBuffer, const String8& mimeType);
+
+ /**
+ * Destructor for DrmInfo
+ */
+ virtual ~DrmInfo() {}
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmInfo;
+
+ private:
+ KeyIterator(const DrmInfo* drmInfo)
+ : mDrmInfo(const_cast <DrmInfo*> (drmInfo)), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmInfo* mDrmInfo;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator
+ */
+ class Iterator {
+ friend class DrmInfo;
+
+ private:
+ Iterator(const DrmInfo* drmInfo)
+ : mDrmInfo(const_cast <DrmInfo*> (drmInfo)), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmInfo* mDrmInfo;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ int getInfoType(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the trigger data associated with this instance
+ *
+ * @return Trigger data
+ */
+ const DrmBuffer& getData(void) const;
+
+ /**
+ * Returns the number of attributes contained in this instance
+ *
+ * @return Number of attributes
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds optional information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns the error code
+ */
+ status_t put(const String8& key, const String8& value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator() const;
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator() const;
+
+ /**
+ * Returns index of the given key
+ *
+ * @return index
+ */
+ int indexOfKey(const String8& key) const;
+
+protected:
+ int mInfoType;
+ DrmBuffer mData;
+ String8 mMimeType;
+ KeyedVector<String8, String8> mAttributes;
+};
+
+};
+
+#endif /* __DRM_INFO_H__ */
+
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
new file mode 100644
index 0000000..7b409ff
--- /dev/null
+++ b/include/drm/DrmInfoEvent.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 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_INFO_EVENT_H__
+#define __DRM_INFO_EVENT_H__
+
+namespace android {
+
+class String8;
+
+/**
+ * This is an entity class which would be passed to caller in
+ * DrmManagerClient::OnInfoListener::onInfo(const DrmInfoEvent&).
+ */
+class DrmInfoEvent {
+public:
+ /**
+ * The following constant values should be in sync with DrmInfoEvent.java
+ */
+ //! TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT, when registration has been
+ //! already done by another account ID.
+ static const int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 1;
+ //! TYPE_REMOVE_RIGHTS, when the rights needs to be removed completely.
+ static const int TYPE_REMOVE_RIGHTS = 2;
+ //! TYPE_RIGHTS_INSTALLED, when the rights are downloaded and installed ok.
+ static const int TYPE_RIGHTS_INSTALLED = 3;
+ //! TYPE_WAIT_FOR_RIGHTS, rights object is on it's way to phone,
+ //! wait before calling checkRights again
+ static const int TYPE_WAIT_FOR_RIGHTS = 4;
+ //! TYPE_ACCOUNT_ALREADY_REGISTERED, when registration has been
+ //! already done for the given account.
+ static const int TYPE_ACCOUNT_ALREADY_REGISTERED = 5;
+
+ /**
+ * The following constant values should be in sync with DrmErrorEvent.java
+ */
+ //! TYPE_RIGHTS_NOT_INSTALLED, when something went wrong installing the rights
+ static const int TYPE_RIGHTS_NOT_INSTALLED = 2001;
+ //! TYPE_RIGHTS_RENEWAL_NOT_ALLOWED, when the server rejects renewal of rights
+ static const int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 2002;
+ //! TYPE_NOT_SUPPORTED, when answer from server can not be handled by the native agent
+ static const int TYPE_NOT_SUPPORTED = 2003;
+ //! TYPE_OUT_OF_MEMORY, when memory allocation fail during renewal.
+ //! Can in the future perhaps be used to trigger garbage collector
+ static const int TYPE_OUT_OF_MEMORY = 2004;
+ //! TYPE_NO_INTERNET_CONNECTION, when the Internet connection is missing and no attempt
+ //! can be made to renew rights
+ static const int TYPE_NO_INTERNET_CONNECTION = 2005;
+ //! TYPE_PROCESS_DRM_INFO_FAILED, when failed to process DrmInfo.
+ static const int TYPE_PROCESS_DRM_INFO_FAILED = 2006;
+
+public:
+ /**
+ * Constructor for DrmInfoEvent
+ *
+ * @param[in] uniqueId Unique session identifier
+ * @param[in] infoType Type of information
+ * @param[in] message Message description
+ */
+ DrmInfoEvent(int uniqueId, int infoType, const String8& message);
+
+ /**
+ * Destructor for DrmInfoEvent
+ */
+ virtual ~DrmInfoEvent() {}
+
+public:
+ /**
+ * Returns the Unique Id associated with this instance
+ *
+ * @return Unique Id
+ */
+ int getUniqueId() const;
+
+ /**
+ * Returns the Type of information associated with this object
+ *
+ * @return Type of information
+ */
+ int getType() const;
+
+ /**
+ * Returns the message description associated with this object
+ *
+ * @return Message description
+ */
+ const String8& getMessage() const;
+
+private:
+ int mUniqueId;
+ int mInfoType;
+ const String8& mMessage;
+};
+
+};
+
+#endif /* __DRM_INFO_EVENT_H__ */
+
diff --git a/include/drm/DrmInfoRequest.h b/include/drm/DrmInfoRequest.h
new file mode 100644
index 0000000..3e48ecc
--- /dev/null
+++ b/include/drm/DrmInfoRequest.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2010 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_INFO_REQUEST_H__
+#define __DRM_INFO_REQUEST_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class used to pass required parameters to get
+ * the necessary information to communicate with online DRM server
+ *
+ * An instance of this class is passed to
+ * DrmManagerClient::acquireDrmInfo(const DrmInfoRequest*) to get the
+ * instance of DrmInfo.
+ *
+ */
+class DrmInfoRequest {
+public:
+ // Changes in following constants should be in sync with DrmInfoRequest.java
+ static const int TYPE_REGISTRATION_INFO = 1;
+ static const int TYPE_UNREGISTRATION_INFO = 2;
+ static const int TYPE_RIGHTS_ACQUISITION_INFO = 3;
+ static const int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4;
+
+ /**
+ * Key to pass the unique id for the account or the user
+ */
+ static const String8 ACCOUNT_ID;
+ /**
+ * Key to pass the subscription id
+ */
+ static const String8 SUBSCRIPTION_ID;
+
+public:
+ /**
+ * Constructor for DrmInfoRequest
+ *
+ * @param[in] infoType Type of information
+ * @param[in] mimeType MIME type
+ */
+ DrmInfoRequest(int infoType, const String8& mimeType);
+
+ /**
+ * Destructor for DrmInfoRequest
+ */
+ virtual ~DrmInfoRequest() {}
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmInfoRequest;
+
+ private:
+ KeyIterator(const DrmInfoRequest* drmInfoRequest)
+ : mDrmInfoRequest(const_cast <DrmInfoRequest*> (drmInfoRequest)), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmInfoRequest* mDrmInfoRequest;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator
+ */
+ class Iterator {
+ friend class DrmInfoRequest;
+
+ private:
+ Iterator(const DrmInfoRequest* drmInfoRequest)
+ : mDrmInfoRequest(const_cast <DrmInfoRequest*> (drmInfoRequest)), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmInfoRequest* mDrmInfoRequest;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ int getInfoType(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the number of entries in DrmRequestInfoMap
+ *
+ * @return Number of entries
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds optional information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns the error code
+ */
+ status_t put(const String8& key, const String8& value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator() const;
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator() const;
+
+private:
+ int mInfoType;
+ String8 mMimeType;
+
+ typedef KeyedVector<String8, String8> DrmRequestInfoMap;
+ DrmRequestInfoMap mRequestInformationMap;
+};
+
+};
+
+#endif /* __DRM_INFO_REQUEST_H__ */
+
diff --git a/include/drm/DrmInfoStatus.h b/include/drm/DrmInfoStatus.h
new file mode 100644
index 0000000..88c0f40
--- /dev/null
+++ b/include/drm/DrmInfoStatus.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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_INFO_STATUS_H__
+#define __DRM_INFO_STATUS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the result of communication between device
+ * and online DRM server.
+ *
+ * As a result of DrmManagerClient::processDrmInfo(const DrmInfo*) an instance of
+ * DrmInfoStatus would be returned. This class holds DrmBuffer which could be
+ * used to instantiate DrmRights in license acquisition.
+ *
+ */
+class DrmInfoStatus {
+public:
+ // Should be in sync with DrmInfoStatus.java
+ static const int STATUS_OK = 1;
+ static const int STATUS_ERROR = 2;
+
+public:
+ /**
+ * Constructor for DrmInfoStatus
+ *
+ * @param[in] _statusCode Status of the communication
+ * @param[in] _infoType Type of the DRM information processed
+ * @param[in] _drmBuffer Rights information
+ * @param[in] _mimeType MIME type
+ */
+ DrmInfoStatus(int _statusCode, int _infoType, const DrmBuffer* _drmBuffer, const String8& _mimeType);
+
+ /**
+ * Destructor for DrmInfoStatus
+ */
+ virtual ~DrmInfoStatus() {
+
+ }
+
+public:
+ int statusCode;
+ int infoType;
+ const DrmBuffer* drmBuffer;
+ String8 mimeType;
+};
+
+};
+
+#endif /* __DRM_INFO_STATUS_H__ */
+
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
new file mode 100644
index 0000000..3dbfbe2
--- /dev/null
+++ b/include/drm/DrmManagerClient.h
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2010 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_MANAGER_CLIENT_H__
+#define __DRM_MANAGER_CLIENT_H__
+
+#include <utils/threads.h>
+#include <binder/IInterface.h>
+#include "drm_framework_common.h"
+
+namespace android {
+
+class DrmInfo;
+class DrmRights;
+class DrmMetadata;
+class DrmInfoEvent;
+class DrmInfoStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmConstraints;
+class DrmConvertedStatus;
+class DrmManagerClientImpl;
+
+/**
+ * The Native application will instantiate this class and access DRM Framework
+ * services through this class.
+ *
+ */
+class DrmManagerClient {
+public:
+ DrmManagerClient();
+
+ virtual ~DrmManagerClient();
+
+public:
+ class OnInfoListener: virtual public RefBase {
+
+ public:
+ virtual void onInfo(const DrmInfoEvent& event) = 0;
+ };
+
+/**
+ * APIs which will be used by native modules (e.g. StageFright)
+ *
+ */
+public:
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * Handle for the decryption session
+ */
+ DecryptHandle* openDecryptSession(int fd, int offset, int length);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uri Path of the protected content to be decrypted
+ * @return
+ * Handle for the decryption session
+ */
+ DecryptHandle* openDecryptSession(const char* uri);
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t closeDecryptSession(DecryptHandle* decryptHandle);
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure.
+ * In case license has been expired, DRM_ERROR_LICENSE_EXPIRED will be returned.
+ */
+ status_t consumeRights(DecryptHandle* decryptHandle, int action, bool reserve);
+
+ /**
+ * Informs the DRM engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t initializeDecryptUnit(
+ DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ status_t decrypt(
+ DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV = NULL);
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId);
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset);
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ bool validateAction(const String8& path, int action, const ActionDescription& description);
+
+/**
+ * APIs which are just the underlying implementation for the Java API
+ *
+ */
+public:
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setOnInfoListener(const sp<DrmManagerClient::OnInfoListener>& infoListener);
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmConstraints* getConstraints(const String8* path, const int action);
+
+ /**
+ * Get metadata information associated with input content
+ *
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata
+ * @note
+ * In case of error, return NULL
+ */
+ DrmMetadata* getMetadata(const String8* path);
+
+ /**
+ * Check whether the given mimetype or path can be handled
+ *
+ * @param[in] path Path of the content needs to be handled
+ * @param[in] mimetype Mimetype of the content needs to be handled
+ * @return
+ * True if DrmManager can handle given path or mime type.
+ */
+ bool canHandle(const String8& path, const String8& mimeType);
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ DrmInfoStatus* processDrmInfo(const DrmInfo* drmInfo);
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ DrmInfo* acquireDrmInfo(const DrmInfoRequest* drmInfoRequest);
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t saveRights(
+ const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath);
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] path the path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ String8 getOriginalMimeType(const String8& path);
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * by using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ int getDrmObjectType(const String8& path, const String8& mimeType);
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ int checkRightsStatus(const String8& path, int action);
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeRights(const String8& path);
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeAllRights();
+
+ /**
+ * This API is for Forward Lock DRM.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @param[in] mimeType Description/MIME type of the input data packet
+ * @return Return handle for the convert session
+ */
+ int openConvertSession(const String8& mimeType);
+
+ /**
+ * Passes the input data which need to be converted. The resultant
+ * converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ DrmConvertedStatus* convertData(int convertId, const DrmBuffer* inputData);
+
+ /**
+ * When there is no more data which need to be converted or when an
+ * error occurs that time the application has to inform the Drm agent
+ * via this API. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ DrmConvertedStatus* closeConvertSession(int convertId);
+
+ /**
+ * Retrieves all DrmSupportInfo instance that native DRM framework can handle.
+ * This interface is meant to be used by JNI layer
+ *
+ * @param[out] length Number of elements in drmSupportInfoArray
+ * @param[out] drmSupportInfoArray Array contains all DrmSupportInfo
+ * that native DRM framework can handle
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray);
+
+private:
+ int mUniqueId;
+ Mutex mDecryptLock;
+ DrmManagerClientImpl* mDrmManagerClientImpl;
+};
+
+};
+
+#endif /* __DRM_MANAGER_CLIENT_H__ */
+
diff --git a/include/drm/DrmMetadata.h b/include/drm/DrmMetadata.h
new file mode 100644
index 0000000..2c7538a
--- /dev/null
+++ b/include/drm/DrmMetadata.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 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_METADATA_H__
+#define __DRM_METADATA_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which contains the constraints information.
+ *
+ * As a result of DrmManagerClient::getMetadata(const String8*)
+ * an instance of DrmMetadata would be returned.
+ */
+class DrmMetadata {
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmMetadata;
+ private:
+ KeyIterator(DrmMetadata* drmMetadata) : mDrmMetadata(drmMetadata), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmMetadata* mDrmMetadata;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for constraints
+ */
+ class Iterator {
+ friend class DrmMetadata;
+ private:
+ Iterator(DrmMetadata* drmMetadata) : mDrmMetadata(drmMetadata), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8 next();
+
+ private:
+ DrmMetadata* mDrmMetadata;
+ unsigned int mIndex;
+ };
+
+public:
+ DrmMetadata() {}
+ virtual ~DrmMetadata() {
+ DrmMetadata::KeyIterator keyIt = this->keyIterator();
+
+ while (keyIt.hasNext()) {
+ String8 key = keyIt.next();
+ const char* value = this->getAsByteArray(&key);
+ if (NULL != value) {
+ delete[] value;
+ value = NULL;
+ }
+ }
+ mMetadataMap.clear();
+ }
+
+public:
+ int getCount(void) const;
+ status_t put(const String8* key, const char* value);
+ String8 get(const String8& key) const;
+ const char* getAsByteArray(const String8* key) const;
+ KeyIterator keyIterator();
+ Iterator iterator();
+
+private:
+ const char* getValue(const String8* key) const;
+
+private:
+ typedef KeyedVector<String8, const char*> DrmMetadataMap;
+ DrmMetadataMap mMetadataMap;
+};
+
+};
+
+#endif /* __DRM_METADATA_H__ */
+
diff --git a/include/drm/DrmRights.h b/include/drm/DrmRights.h
new file mode 100644
index 0000000..11f8f78
--- /dev/null
+++ b/include/drm/DrmRights.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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_RIGHTS_H__
+#define __DRM_RIGHTS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the license information which was
+ * retrieved from the online DRM server.
+ *
+ * Caller can instantiate DrmRights by invoking DrmRights(const DrmBuffer&, String)
+ * constructor by using the result of DrmManagerClient::ProcessDrmInfo(const DrmInfo*) API.
+ * Caller can also instantiate DrmRights using the file path which contains rights information.
+ *
+ */
+class DrmRights {
+public:
+ /**
+ * Constructor for DrmRights
+ *
+ * @param[in] rightsFilePath Path of the file containing rights data
+ * @param[in] mimeType MIME type
+ * @param[in] accountId Account Id of the user
+ * @param[in] subscriptionId Subscription Id of the user
+ */
+ DrmRights(
+ const String8& rightsFilePath, const String8& mimeType,
+ const String8& accountId = String8("_NO_USER"),
+ const String8& subscriptionId = String8(""));
+
+ /**
+ * Constructor for DrmRights
+ *
+ * @param[in] rightsData Rights data
+ * @param[in] mimeType MIME type
+ * @param[in] accountId Account Id of the user
+ * @param[in] subscriptionId Subscription Id of the user
+ */
+ DrmRights(
+ const DrmBuffer& rightsData, const String8& mimeType,
+ const String8& accountId = String8("_NO_USER"),
+ const String8& subscriptionId = String8(""));
+
+ /**
+ * Destructor for DrmRights
+ */
+ virtual ~DrmRights();
+
+public:
+ /**
+ * Returns the rights data associated with this instance
+ *
+ * @return Rights data
+ */
+ const DrmBuffer& getData(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the account-id associated with this instance
+ *
+ * @return Account Id
+ */
+ String8 getAccountId(void) const;
+
+ /**
+ * Returns the subscription-id associated with this object
+ *
+ * @return Subscription Id
+ */
+ String8 getSubscriptionId(void) const;
+
+private:
+ DrmBuffer mData;
+ String8 mMimeType;
+ String8 mAccountId;
+ String8 mSubscriptionId;
+ char* mRightsFromFile;
+};
+
+};
+
+#endif /* __DRM_RIGHTS_H__ */
+
diff --git a/include/drm/DrmSupportInfo.h b/include/drm/DrmSupportInfo.h
new file mode 100644
index 0000000..bf12b0b
--- /dev/null
+++ b/include/drm/DrmSupportInfo.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2010 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_SUPPORT_INFO_H__
+#define __DRM_SUPPORT_INFO_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the capability of each plug-in,
+ * such as mimetype's and file suffixes it could handle.
+ *
+ * Plug-in developer could return the capability of the plugin by passing
+ * DrmSupportInfo instance.
+ *
+ */
+class DrmSupportInfo {
+public:
+ /**
+ * Iterator for mMimeTypeVector
+ */
+ class MimeTypeIterator {
+ friend class DrmSupportInfo;
+ private:
+ MimeTypeIterator(DrmSupportInfo* drmSupportInfo)
+ : mDrmSupportInfo(drmSupportInfo), mIndex(0) {}
+ public:
+ MimeTypeIterator(const MimeTypeIterator& iterator);
+ MimeTypeIterator& operator=(const MimeTypeIterator& iterator);
+ virtual ~MimeTypeIterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmSupportInfo* mDrmSupportInfo;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for mFileSuffixVector
+ */
+ class FileSuffixIterator {
+ friend class DrmSupportInfo;
+
+ private:
+ FileSuffixIterator(DrmSupportInfo* drmSupportInfo)
+ : mDrmSupportInfo(drmSupportInfo), mIndex(0) {}
+ public:
+ FileSuffixIterator(const FileSuffixIterator& iterator);
+ FileSuffixIterator& operator=(const FileSuffixIterator& iterator);
+ virtual ~FileSuffixIterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmSupportInfo* mDrmSupportInfo;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Constructor for DrmSupportInfo
+ */
+ DrmSupportInfo();
+
+ /**
+ * Copy constructor for DrmSupportInfo
+ */
+ DrmSupportInfo(const DrmSupportInfo& drmSupportInfo);
+
+ /**
+ * Destructor for DrmSupportInfo
+ */
+ virtual ~DrmSupportInfo() {}
+
+ DrmSupportInfo& operator=(const DrmSupportInfo& drmSupportInfo);
+ bool operator<(const DrmSupportInfo& drmSupportInfo) const;
+ bool operator==(const DrmSupportInfo& drmSupportInfo) const;
+
+ /**
+ * Returns FileSuffixIterator object to walk through file suffix values
+ * associated with this instance
+ *
+ * @return FileSuffixIterator object
+ */
+ FileSuffixIterator getFileSuffixIterator();
+
+ /**
+ * Returns MimeTypeIterator object to walk through mimetype values
+ * associated with this instance
+ *
+ * @return MimeTypeIterator object
+ */
+ MimeTypeIterator getMimeTypeIterator();
+
+public:
+ /**
+ * Returns the number of mimetypes supported.
+ *
+ * @return Number of mimetypes supported
+ */
+ int getMimeTypeCount(void) const;
+
+ /**
+ * Returns the number of file types supported.
+ *
+ * @return Number of file types supported
+ */
+ int getFileSuffixCount(void) const;
+
+ /**
+ * Adds the mimetype to the list of supported mimetypes
+ *
+ * @param[in] mimeType mimetype to be added
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t addMimeType(const String8& mimeType);
+
+ /**
+ * Adds the filesuffix to the list of supported file types
+ *
+ * @param[in] filesuffix file suffix to be added
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t addFileSuffix(const String8& fileSuffix);
+
+ /**
+ * Set the unique description about the plugin
+ *
+ * @param[in] description Unique description
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setDescription(const String8& description);
+
+ /**
+ * Returns the unique description associated with the plugin
+ *
+ * @return Unique description
+ */
+ String8 getDescription() const;
+
+ /**
+ * Returns whether given mimetype is supported or not
+ *
+ * @param[in] mimeType MIME type
+ * @return
+ * true - if mime-type is supported
+ * false - if mime-type is not supported
+ */
+ bool isSupportedMimeType(const String8& mimeType) const;
+
+ /**
+ * Returns whether given file type is supported or not
+ *
+ * @param[in] fileType File type
+ * @return
+ * true if file type is supported
+ * false if file type is not supported
+ */
+ bool isSupportedFileSuffix(const String8& fileType) const;
+
+private:
+ Vector<String8> mMimeTypeVector;
+ Vector<String8> mFileSuffixVector;
+
+ String8 mDescription;
+};
+
+};
+
+#endif /* __DRM_SUPPORT_INFO_H__ */
+
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
new file mode 100644
index 0000000..c5765a9
--- /dev/null
+++ b/include/drm/drm_framework_common.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2010 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_FRAMEWORK_COMMON_H__
+#define __DRM_FRAMEWORK_COMMON_H__
+
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+
+#define INVALID_VALUE -1
+
+namespace android {
+
+/**
+ * Error code for DRM Frameowrk
+ */
+enum {
+ DRM_ERROR_BASE = -2000,
+
+ DRM_ERROR_UNKNOWN = DRM_ERROR_BASE,
+ DRM_ERROR_LICENSE_EXPIRED = DRM_ERROR_BASE - 1,
+ DRM_ERROR_SESSION_NOT_OPENED = DRM_ERROR_BASE - 2,
+ DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 3,
+ DRM_ERROR_DECRYPT = DRM_ERROR_BASE - 4,
+ DRM_ERROR_CANNOT_HANDLE = DRM_ERROR_BASE - 5,
+
+ DRM_NO_ERROR = NO_ERROR
+};
+
+/**
+ * Defines DRM Buffer
+ */
+class DrmBuffer {
+public:
+ char* data;
+ int length;
+
+ DrmBuffer() :
+ data(NULL),
+ length(0) {
+ }
+
+ DrmBuffer(char* dataBytes, int dataLength) :
+ data(dataBytes),
+ length(dataLength) {
+ }
+
+};
+
+/**
+ * Defines detailed description of the action
+ */
+class ActionDescription {
+public:
+ ActionDescription(int _outputType, int _configuration) :
+ outputType(_outputType),
+ configuration(_configuration) {
+ }
+
+public:
+ int outputType; /* BLUETOOTH , HDMI*/
+ int configuration; /* RESOLUTION_720_480 , RECORDABLE etc.*/
+};
+
+/**
+ * Defines constants related to DRM types
+ */
+class DrmObjectType {
+private:
+ DrmObjectType();
+
+public:
+ /**
+ * Field specifies the unknown type
+ */
+ static const int UNKNOWN = 0x00;
+ /**
+ * Field specifies the protected content type
+ */
+ static const int CONTENT = 0x01;
+ /**
+ * Field specifies the rights information
+ */
+ static const int RIGHTS_OBJECT = 0x02;
+ /**
+ * Field specifies the trigger information
+ */
+ static const int TRIGGER_OBJECT = 0x03;
+};
+
+/**
+ * Defines constants related to play back
+ */
+class Playback {
+private:
+ Playback();
+
+public:
+ /**
+ * Constant field signifies playback start
+ */
+ static const int START = 0x00;
+ /**
+ * Constant field signifies playback stop
+ */
+ static const int STOP = 0x01;
+ /**
+ * Constant field signifies playback paused
+ */
+ static const int PAUSE = 0x02;
+ /**
+ * Constant field signifies playback resumed
+ */
+ static const int RESUME = 0x03;
+};
+
+/**
+ * Defines actions that can be performed on protected content
+ */
+class Action {
+private:
+ Action();
+
+public:
+ /**
+ * Constant field signifies that the default action
+ */
+ static const int DEFAULT = 0x00;
+ /**
+ * Constant field signifies that the content can be played
+ */
+ static const int PLAY = 0x01;
+ /**
+ * Constant field signifies that the content can be set as ring tone
+ */
+ static const int RINGTONE = 0x02;
+ /**
+ * Constant field signifies that the content can be transfered
+ */
+ static const int TRANSFER = 0x03;
+ /**
+ * Constant field signifies that the content can be set as output
+ */
+ static const int OUTPUT = 0x04;
+ /**
+ * Constant field signifies that preview is allowed
+ */
+ static const int PREVIEW = 0x05;
+ /**
+ * Constant field signifies that the content can be executed
+ */
+ static const int EXECUTE = 0x06;
+ /**
+ * Constant field signifies that the content can displayed
+ */
+ static const int DISPLAY = 0x07;
+};
+
+/**
+ * Defines constants related to status of the rights
+ */
+class RightsStatus {
+private:
+ RightsStatus();
+
+public:
+ /**
+ * Constant field signifies that the rights are valid
+ */
+ static const int RIGHTS_VALID = 0x00;
+ /**
+ * Constant field signifies that the rights are invalid
+ */
+ static const int RIGHTS_INVALID = 0x01;
+ /**
+ * Constant field signifies that the rights are expired for the content
+ */
+ static const int RIGHTS_EXPIRED = 0x02;
+ /**
+ * Constant field signifies that the rights are not acquired for the content
+ */
+ static const int RIGHTS_NOT_ACQUIRED = 0x03;
+};
+
+/**
+ * Defines API set for decryption
+ */
+class DecryptApiType {
+private:
+ DecryptApiType();
+
+public:
+ /**
+ * Decrypt API set for non encrypted content
+ */
+ static const int NON_ENCRYPTED = 0x00;
+ /**
+ * Decrypt API set for ES based DRM
+ */
+ static const int ELEMENTARY_STREAM_BASED = 0x01;
+ /**
+ * POSIX based Decrypt API set for container based DRM
+ */
+ static const int CONTAINER_BASED = 0x02;
+};
+
+/**
+ * Defines decryption information
+ */
+class DecryptInfo {
+public:
+ /**
+ * size of memory to be allocated to get the decrypted content.
+ */
+ int decryptBufferLength;
+ /**
+ * reserved for future purpose
+ */
+};
+
+/**
+ * Defines decryption handle
+ */
+class DecryptHandle {
+public:
+ /**
+ * Decryption session Handle
+ */
+ int decryptId;
+ /**
+ * Mimetype of the content to be used to select the media extractor
+ * For e.g., "video/mpeg" or "audio/mp3"
+ */
+ String8 mimeType;
+ /**
+ * Defines which decryption pattern should be used to decrypt the given content
+ * DrmFramework provides two different set of decryption APIs.
+ * 1. Decrypt APIs for elementary stream based DRM
+ * (file format is not encrypted but ES is encrypted)
+ * e.g., Marlin DRM (MP4 file format), WM-DRM (asf file format)
+ *
+ * DecryptApiType::ELEMENTARY_STREAM_BASED
+ * Decryption API set for ES based DRM
+ * initializeDecryptUnit(), decrypt(), and finalizeDecryptUnit()
+ * 2. Decrypt APIs for container based DRM (file format itself is encrypted)
+ * e.g., OMA DRM (dcf file format)
+ *
+ * DecryptApiType::CONTAINER_BASED
+ * POSIX based Decryption API set for container based DRM
+ * pread()
+ */
+ int decryptApiType;
+ /**
+ * Defines the status of the rights like
+ * RIGHTS_VALID, RIGHTS_INVALID, RIGHTS_EXPIRED or RIGHTS_NOT_ACQUIRED
+ */
+ int status;
+ /**
+ * Information required to decrypt content
+ * e.g. size of memory to be allocated to get the decrypted content.
+ */
+ DecryptInfo* decryptInfo;
+
+public:
+ DecryptHandle():
+ decryptId(INVALID_VALUE),
+ mimeType(""),
+ decryptApiType(INVALID_VALUE),
+ status(INVALID_VALUE) {
+
+ }
+
+ bool operator<(const DecryptHandle& handle) const {
+ return (decryptId < handle.decryptId);
+ }
+
+ bool operator==(const DecryptHandle& handle) const {
+ return (decryptId == handle.decryptId);
+ }
+};
+
+};
+
+#endif /* __DRM_FRAMEWORK_COMMON_H__ */
+
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index a3da3ed..d0b9fcd 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -25,6 +25,7 @@
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
namespace android {
@@ -73,6 +74,13 @@
static void RegisterSniffer(SnifferFunc func);
static void RegisterDefaultSniffers();
+ // for DRM
+ virtual DecryptHandle* DrmInitialization(DrmManagerClient *client) {
+ return NULL;
+ }
+ virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {};
+
+
protected:
virtual ~DataSource() {}
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index 8a215ea..4307263 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -23,6 +23,7 @@
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
namespace android {
@@ -37,15 +38,29 @@
virtual status_t getSize(off_t *size);
+ virtual DecryptHandle* DrmInitialization(DrmManagerClient *client);
+
+ virtual void getDrmInfo(DecryptHandle **handle, DrmManagerClient **client);
+
protected:
virtual ~FileSource();
private:
FILE *mFile;
+ int mFd;
int64_t mOffset;
int64_t mLength;
Mutex mLock;
+ /*for DRM*/
+ DecryptHandle *mDecryptHandle;
+ DrmManagerClient *mDrmManagerClient;
+ int64_t mDrmBufOffset;
+ int64_t mDrmBufSize;
+ unsigned char *mDrmBuf;
+
+ ssize_t readAtDRM(off_t offset, void *data, size_t size);
+
FileSource(const FileSource &);
FileSource &operator=(const FileSource &);
};
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index e44122d..6df4d86 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -40,6 +40,8 @@
// Not technically an error.
INFO_FORMAT_CHANGED = MEDIA_ERROR_BASE - 12,
INFO_DISCONTINUITY = MEDIA_ERROR_BASE - 13,
+
+ ERROR_NO_LICENSE = MEDIA_ERROR_BASE - 14,
};
} // namespace android
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 16b0a4c..a82106e 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -55,6 +55,12 @@
// CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
virtual uint32_t flags() const;
+ // for DRM
+ virtual void setDrmFlag(bool flag) {};
+ virtual char* getDrmTrackInfo(size_t trackID, int *len) {
+ return NULL;
+ }
+
protected:
MediaExtractor() {}
virtual ~MediaExtractor() {}
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 29bfc4a..a69d9af 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -58,6 +58,8 @@
kKeyBufferID = 'bfID',
kKeyMaxInputSize = 'inpS',
kKeyThumbnailTime = 'thbT', // int64_t (usecs)
+ kKeyTrackID = 'trID',
+ kKeyIsDRM = 'idrm', // int32_t (bool)
kKeyAlbum = 'albu', // cstring
kKeyArtist = 'arti', // cstring
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 6f581d3..c5112a5 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -81,13 +81,13 @@
}
static bool fileMatchesExtension(const char* path, const char* extensions) {
- char* extension = strrchr(path, '.');
+ const char* extension = strrchr(path, '.');
if (!extension) return false;
++extension; // skip the dot
if (extension[0] == 0) return false;
while (extensions[0]) {
- char* comma = strchr(extensions, ',');
+ const char* comma = strchr(extensions, ',');
size_t length = (comma ? comma - extensions : strlen(extensions));
if (length == strlen(extension) && strncasecmp(extension, extensions, length) == 0) return true;
extensions += length;
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 615f3e8..d674547 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -11,6 +11,7 @@
AwesomePlayer.cpp \
CameraSource.cpp \
DataSource.cpp \
+ DRMExtractor.cpp \
ESDS.cpp \
FileSource.cpp \
HTTPStream.cpp \
@@ -59,7 +60,8 @@
libsonivox \
libvorbisidec \
libsurfaceflinger_client \
- libcamera_client
+ libcamera_client \
+ libdrmframework
LOCAL_STATIC_LIBRARIES := \
libstagefright_aacdec \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 08cf515..44d12e5 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -245,7 +245,8 @@
mExtractorFlags(0),
mLastVideoBuffer(NULL),
mVideoBuffer(NULL),
- mSuspensionState(NULL) {
+ mSuspensionState(NULL),
+ mDecryptHandle(NULL) {
CHECK_EQ(mClient.connect(), OK);
DataSource::RegisterDefaultSniffers();
@@ -344,6 +345,12 @@
return UNKNOWN_ERROR;
}
+ dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+ if (mDecryptHandle != NULL
+ && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
+ }
+
return setDataSource_l(extractor);
}
@@ -419,6 +426,13 @@
}
void AwesomePlayer::reset_l() {
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::STOP, 0);
+ mDecryptHandle = NULL;
+ mDrmManagerClient = NULL;
+ }
+
if (mFlags & PREPARING) {
mFlags |= PREPARE_CANCELLED;
if (mConnectingDataSource != NULL) {
@@ -762,6 +776,13 @@
bool deferredAudioSeek = false;
+ if (mDecryptHandle != NULL) {
+ int64_t position;
+ getPosition(&position);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, position / 1000);
+ }
+
if (mAudioSource != NULL) {
if (mAudioPlayer == NULL) {
if (mAudioSink != NULL) {
@@ -779,6 +800,11 @@
mFlags &= ~(PLAYING | FIRST_FRAME);
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::STOP, 0);
+ }
+
return err;
}
@@ -906,6 +932,11 @@
mFlags &= ~PLAYING;
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ }
+
return OK;
}
@@ -1023,6 +1054,13 @@
mWatchForAudioSeekComplete = true;
mWatchForAudioEOS = true;
mSeekNotificationSent = false;
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, mSeekTimeUs / 1000);
+ }
}
}
@@ -1253,6 +1291,13 @@
TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, timeUs / 1000);
+ }
+
if (mFlags & FIRST_FRAME) {
mFlags &= ~FIRST_FRAME;
@@ -1636,6 +1681,12 @@
return UNKNOWN_ERROR;
}
+ dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
+ if (mDecryptHandle != NULL
+ && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
+ }
+
return setDataSource_l(extractor);
}
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
new file mode 100644
index 0000000..aa9ad23
--- /dev/null
+++ b/media/libstagefright/DRMExtractor.cpp
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "include/DRMExtractor.h"
+#include "include/AMRExtractor.h"
+#include "include/MP3Extractor.h"
+#include "include/MPEG4Extractor.h"
+#include "include/WAVExtractor.h"
+#include "include/OggExtractor.h"
+
+#include <arpa/inet.h>
+#include <utils/String8.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDebug.h>
+
+#include <drm/drm_framework_common.h>
+#include <utils/Errors.h>
+
+
+namespace android {
+
+DrmManagerClient* gDrmManagerClient = NULL;
+
+class DRMSource : public MediaSource {
+public:
+ DRMSource(const sp<MediaSource> &mediaSource,
+ DecryptHandle* decryptHandle, int32_t trackId, DrmBuffer* ipmpBox);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~DRMSource();
+
+private:
+ sp<MediaSource> mOriginalMediaSource;
+ DecryptHandle* mDecryptHandle;
+ size_t mTrackId;
+ mutable Mutex mDRMLock;
+ size_t mNALLengthSize;
+ bool mWantsNALFragments;
+
+ DRMSource(const DRMSource &);
+ DRMSource &operator=(const DRMSource &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
+ DecryptHandle* decryptHandle, int32_t trackId, DrmBuffer* ipmpBox)
+ : mOriginalMediaSource(mediaSource),
+ mDecryptHandle(decryptHandle),
+ mTrackId(trackId),
+ mNALLengthSize(0),
+ mWantsNALFragments(false) {
+ gDrmManagerClient->initializeDecryptUnit(
+ mDecryptHandle, trackId, ipmpBox);
+
+ const char *mime;
+ bool success = getFormat()->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ CHECK(getFormat()->findData(kKeyAVCC, &type, &data, &size));
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ(ptr[0], 1); // configurationVersion == 1
+
+ // The number of bytes used to encode the length of a NAL unit.
+ mNALLengthSize = 1 + (ptr[4] & 3);
+ }
+}
+
+DRMSource::~DRMSource() {
+ Mutex::Autolock autoLock(mDRMLock);
+ gDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
+}
+
+status_t DRMSource::start(MetaData *params) {
+ int32_t val;
+ if (params && params->findInt32(kKeyWantsNALFragments, &val)
+ && val != 0) {
+ mWantsNALFragments = true;
+ } else {
+ mWantsNALFragments = false;
+ }
+
+ return mOriginalMediaSource->start(params);
+}
+
+status_t DRMSource::stop() {
+ return mOriginalMediaSource->stop();
+}
+
+sp<MetaData> DRMSource::getFormat() {
+ return mOriginalMediaSource->getFormat();
+}
+
+status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
+ Mutex::Autolock autoLock(mDRMLock);
+ status_t err;
+ if ((err = mOriginalMediaSource->read(buffer, options)) != OK) {
+ return err;
+ }
+
+ size_t len = (*buffer)->range_length();
+
+ char *src = (char *)(*buffer)->data() + (*buffer)->range_offset();
+
+ DrmBuffer encryptedDrmBuffer(src, len);
+ DrmBuffer decryptedDrmBuffer;
+ decryptedDrmBuffer.length = len;
+ decryptedDrmBuffer.data = new char[len];
+ DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;
+
+ if ((err = gDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
+ &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != DRM_NO_ERROR) {
+
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+
+ if (err == DRM_ERROR_LICENSE_EXPIRED) {
+ return ERROR_NO_LICENSE;
+ } else {
+ return ERROR_IO;
+ }
+ }
+ CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer);
+
+ const char *mime;
+ CHECK(getFormat()->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) && !mWantsNALFragments) {
+ uint8_t *dstData = (uint8_t*)src;
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+
+ len = decryptedDrmBuffer.length;
+ while (srcOffset < len) {
+ CHECK(srcOffset + mNALLengthSize <= len);
+ size_t nalLength = 0;
+ const uint8_t* data = (const uint8_t*)(&decryptedDrmBuffer.data[srcOffset]);
+
+ switch (mNALLengthSize) {
+ case 1:
+ nalLength = *data;
+ break;
+ case 2:
+ nalLength = U16_AT(data);
+ break;
+ case 3:
+ nalLength = ((size_t)data[0] << 16) | U16_AT(&data[1]);
+ break;
+ case 4:
+ nalLength = U32_AT(data);
+ break;
+ default:
+ CHECK(!"Should not be here.");
+ break;
+ }
+
+ srcOffset += mNALLengthSize;
+
+ if (srcOffset + nalLength > len) {
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+
+ return ERROR_MALFORMED;
+ }
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ CHECK(dstOffset + 4 <= (*buffer)->size());
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &decryptedDrmBuffer.data[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
+ }
+
+ CHECK_EQ(srcOffset, len);
+ (*buffer)->set_range((*buffer)->range_offset(), dstOffset);
+
+ } else {
+ memcpy(src, decryptedDrmBuffer.data, decryptedDrmBuffer.length);
+ (*buffer)->set_range((*buffer)->range_offset(), decryptedDrmBuffer.length);
+ }
+
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
+ : mDataSource(source),
+ mDecryptHandle(NULL) {
+ mOriginalExtractor = MediaExtractor::Create(source, mime);
+ mOriginalExtractor->setDrmFlag(true);
+
+ DrmManagerClient *client;
+ source->getDrmInfo(&mDecryptHandle, &client);
+}
+
+DRMExtractor::~DRMExtractor() {
+}
+
+size_t DRMExtractor::countTracks() {
+ return mOriginalExtractor->countTracks();
+}
+
+sp<MediaSource> DRMExtractor::getTrack(size_t index) {
+ sp<MediaSource> originalMediaSource = mOriginalExtractor->getTrack(index);
+ originalMediaSource->getFormat()->setInt32(kKeyIsDRM, 1);
+
+ int32_t trackID;
+ CHECK(getTrackMetaData(index, 0)->findInt32(kKeyTrackID, &trackID));
+
+ DrmBuffer ipmpBox;
+ ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length));
+ CHECK(ipmpBox.length > 0);
+
+ return new DRMSource(originalMediaSource, mDecryptHandle, trackID, &ipmpBox);
+}
+
+sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+ return mOriginalExtractor->getTrackMetaData(index, flags);
+}
+
+sp<MetaData> DRMExtractor::getMetaData() {
+ return mOriginalExtractor->getMetaData();
+}
+
+static Mutex gDRMSnifferMutex;
+bool SniffDRM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ {
+ Mutex::Autolock autoLock(gDRMSnifferMutex);
+ if (gDrmManagerClient == NULL) {
+ gDrmManagerClient = new DrmManagerClient();
+ }
+ }
+
+ DecryptHandle *decryptHandle = source->DrmInitialization(gDrmManagerClient);
+
+ if (decryptHandle != NULL) {
+ if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
+ *mimeType = String8("drm+container_based+");
+ } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
+ *mimeType = String8("drm+es_based+");
+ }
+
+ *mimeType += decryptHandle->mimeType;
+ *confidence = 10.0f;
+
+ return true;
+ }
+
+ return false;
+}
+} //namespace android
+
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 49eac62..0b8997c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -22,6 +22,7 @@
#include "include/MPEG2TSExtractor.h"
#include "include/NuCachedSource2.h"
#include "include/NuHTTPDataSource.h"
+#include "include/DRMExtractor.h"
#include "matroska/MatroskaExtractor.h"
@@ -31,6 +32,8 @@
#include <media/stagefright/MediaErrors.h>
#include <utils/String8.h>
+#include <cutils/properties.h>
+
namespace android {
bool DataSource::getUInt16(off_t offset, uint16_t *x) {
@@ -104,6 +107,12 @@
RegisterSniffer(SniffAMR);
RegisterSniffer(SniffMPEG2TS);
RegisterSniffer(SniffMP3);
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("drm.service.enabled", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ RegisterSniffer(SniffDRM);
+ }
}
// static
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index dd2579b..b46d8d0 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -21,14 +21,26 @@
FileSource::FileSource(const char *filename)
: mFile(fopen(filename, "rb")),
+ mFd(fileno(mFile)),
mOffset(0),
- mLength(-1) {
+ mLength(-1),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL),
+ mDrmBufOffset(0),
+ mDrmBufSize(0),
+ mDrmBuf(NULL){
}
FileSource::FileSource(int fd, int64_t offset, int64_t length)
: mFile(fdopen(fd, "rb")),
+ mFd(fd),
mOffset(offset),
- mLength(length) {
+ mLength(length),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL),
+ mDrmBufOffset(0),
+ mDrmBufSize(0),
+ mDrmBuf(NULL){
CHECK(offset >= 0);
CHECK(length >= 0);
}
@@ -38,6 +50,14 @@
fclose(mFile);
mFile = NULL;
}
+
+ if (mDrmBuf != NULL) {
+ delete[] mDrmBuf;
+ mDrmBuf = NULL;
+ }
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ }
}
status_t FileSource::initCheck() const {
@@ -61,13 +81,18 @@
}
}
- int err = fseeko(mFile, offset + mOffset, SEEK_SET);
- if (err < 0) {
- LOGE("seek to %lld failed", offset + mOffset);
- return UNKNOWN_ERROR;
- }
+ if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
+ == mDecryptHandle->decryptApiType) {
+ return readAtDRM(offset, data, size);
+ } else {
+ int err = fseeko(mFile, offset + mOffset, SEEK_SET);
+ if (err < 0) {
+ LOGE("seek to %lld failed", offset + mOffset);
+ return UNKNOWN_ERROR;
+ }
- return fread(data, 1, size, mFile);
+ return fread(data, 1, size, mFile);
+ }
}
status_t FileSource::getSize(off_t *size) {
@@ -87,4 +112,53 @@
return OK;
}
+DecryptHandle* FileSource::DrmInitialization(DrmManagerClient* client) {
+ mDrmManagerClient = client;
+ if (mDecryptHandle == NULL) {
+ mDecryptHandle = mDrmManagerClient->openDecryptSession(
+ mFd, mOffset, mLength);
+ }
+
+ if (mDecryptHandle == NULL) {
+ mDrmManagerClient = NULL;
+ }
+
+ return mDecryptHandle;
+}
+
+void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
+ *handle = mDecryptHandle;
+
+ *client = mDrmManagerClient;
+}
+
+ssize_t FileSource::readAtDRM(off_t offset, void *data, size_t size) {
+ size_t DRM_CACHE_SIZE = 1024;
+ if (mDrmBuf == NULL) {
+ mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
+ }
+
+ if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
+ && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
+ /* Use buffered data */
+ memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
+ return size;
+ } else if (size <= DRM_CACHE_SIZE) {
+ /* Buffer new data */
+ mDrmBufOffset = offset + mOffset;
+ mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
+ DRM_CACHE_SIZE, offset + mOffset);
+ if (mDrmBufSize > 0) {
+ int64_t dataRead = 0;
+ dataRead = size > mDrmBufSize ? mDrmBufSize : size;
+ memcpy(data, (void*)mDrmBuf, dataRead);
+ return dataRead;
+ } else {
+ return mDrmBufSize;
+ }
+ } else {
+ /* Too big chunk to cache. Call DRM directly */
+ return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
+ }
+}
} // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 2154f2f..03682e2 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -264,7 +264,9 @@
mHasVideo(false),
mFirstTrack(NULL),
mLastTrack(NULL),
- mFileMetaData(new MetaData) {
+ mFileMetaData(new MetaData),
+ mFirstSINF(NULL),
+ mIsDrm(false) {
}
MPEG4Extractor::~MPEG4Extractor() {
@@ -276,6 +278,15 @@
track = next;
}
mFirstTrack = mLastTrack = NULL;
+
+ SINF *sinf = mFirstSINF;
+ while (sinf) {
+ SINF *next = sinf->next;
+ delete sinf->IPMPData;
+ delete sinf;
+ sinf = next;
+ }
+ mFirstSINF = NULL;
}
sp<MetaData> MPEG4Extractor::getMetaData() {
@@ -370,6 +381,178 @@
return err;
}
+void MPEG4Extractor::setDrmFlag(bool flag) {
+ mIsDrm = flag;
+}
+
+char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
+ if (mFirstSINF == NULL) {
+ return NULL;
+ }
+
+ SINF *sinf = mFirstSINF;
+ while (sinf && (trackID != sinf->trackID)) {
+ sinf = sinf->next;
+ }
+
+ if (sinf == NULL) {
+ return NULL;
+ }
+
+ *len = sinf->len;
+ return sinf->IPMPData;
+}
+
+// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
+int32_t readSize(off_t offset,
+ const sp<DataSource> DataSource, uint8_t *numOfBytes) {
+ uint32_t size = 0;
+ uint8_t data;
+ bool moreData = true;
+ *numOfBytes = 0;
+
+ while (moreData) {
+ if (DataSource->readAt(offset, &data, 1) < 1) {
+ return -1;
+ }
+ offset ++;
+ moreData = (data >= 128) ? true : false;
+ size = (size << 7) | (data & 0x7f); // Take last 7 bits
+ (*numOfBytes) ++;
+ }
+
+ return size;
+}
+
+status_t MPEG4Extractor::parseDrmSINF(off_t *offset, off_t data_offset) {
+ uint8_t updateIdTag;
+ if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t numOfBytes;
+ int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
+ if (size < 0) {
+ return ERROR_IO;
+ }
+ int32_t classSize = size;
+ data_offset += numOfBytes;
+
+ while(size >= 11 ) {
+ uint8_t descriptorTag;
+ if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t buffer[8];
+ //ObjectDescriptorID and ObjectDescriptor url flag
+ if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
+ return ERROR_IO;
+ }
+ data_offset += 2;
+
+ if ((buffer[1] >> 5) & 0x0001) { //url flag is set
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
+ return ERROR_IO;
+ }
+ data_offset += 8;
+
+ if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
+ || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
+ return ERROR_MALFORMED;
+ }
+
+ SINF *sinf = new SINF;
+ sinf->trackID = U16_AT(&buffer[3]);
+ sinf->IPMPDescriptorID = buffer[7];
+ sinf->next = mFirstSINF;
+ mFirstSINF = sinf;
+
+ size -= (8 + 2 + 1);
+ }
+
+ if (size != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
+ return ERROR_MALFORMED;
+ }
+
+ size = readSize(data_offset, mDataSource, &numOfBytes);
+ if (size < 0) {
+ return ERROR_IO;
+ }
+ classSize = size;
+ data_offset += numOfBytes;
+
+ while (size > 0) {
+ uint8_t tag;
+ int32_t dataLen;
+ if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
+ uint8_t id;
+ dataLen = readSize(data_offset, mDataSource, &numOfBytes);
+ if (dataLen < 0) {
+ return ERROR_IO;
+ } else if (dataLen < 4) {
+ return ERROR_MALFORMED;
+ }
+ data_offset += numOfBytes;
+
+ if (mDataSource->readAt(data_offset, &id, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ SINF *sinf = mFirstSINF;
+ while (sinf && (sinf->IPMPDescriptorID != id)) {
+ sinf = sinf->next;
+ }
+ if (sinf == NULL) {
+ return ERROR_MALFORMED;
+ }
+ sinf->len = dataLen - 3;
+ sinf->IPMPData = new char[sinf->len];
+
+ if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
+ return ERROR_IO;
+ }
+ data_offset += sinf->len;
+
+ size -= (dataLen + numOfBytes + 1);
+ }
+ }
+
+ if (size != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ return UNKNOWN_ERROR; // Return a dummy error.
+}
+
static void MakeFourCCString(uint32_t x, char *s) {
s[0] = x >> 24;
s[1] = (x >> 16) & 0xff;
@@ -572,7 +755,11 @@
} else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
mHaveMetadata = true;
- return UNKNOWN_ERROR; // Return a dummy error.
+ if (!mIsDrm) {
+ return UNKNOWN_ERROR; // Return a dummy error.
+ } else {
+ return OK;
+ }
}
break;
}
@@ -1020,6 +1207,20 @@
break;
}
+ case FOURCC('m', 'd', 'a', 't'):
+ {
+ if (!mIsDrm) {
+ *offset += chunk_size;
+ break;
+ }
+
+ if (chunk_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ return parseDrmSINF(offset, data_offset);
+ }
+
default:
{
*offset += chunk_size;
@@ -1069,6 +1270,8 @@
duration = U32_AT(&buffer[20]);
}
+ mLastTrack->meta->setInt32(kKeyTrackID, id);
+
size_t matrixOffset = dynSize + 16;
int32_t a00 = U32_AT(&buffer[matrixOffset]);
int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
@@ -1701,9 +1904,15 @@
} else {
// Whole NAL units are returned but each fragment is prefixed by
// the start code (0x00 00 00 01).
-
- ssize_t num_bytes_read =
- mDataSource->readAt(offset, mSrcBuffer, size);
+ ssize_t num_bytes_read = 0;
+ int32_t drm = 0;
+ bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+ if (usesDRM) {
+ num_bytes_read =
+ mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
+ } else {
+ num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
+ }
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
@@ -1712,40 +1921,46 @@
return ERROR_IO;
}
- uint8_t *dstData = (uint8_t *)mBuffer->data();
- size_t srcOffset = 0;
- size_t dstOffset = 0;
+ if (usesDRM) {
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, size);
- while (srcOffset < size) {
- CHECK(srcOffset + mNALLengthSize <= size);
- size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
- srcOffset += mNALLengthSize;
+ } else {
+ uint8_t *dstData = (uint8_t *)mBuffer->data();
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
- if (srcOffset + nalLength > size) {
- mBuffer->release();
- mBuffer = NULL;
+ while (srcOffset < size) {
+ CHECK(srcOffset + mNALLengthSize <= size);
+ size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
+ srcOffset += mNALLengthSize;
- return ERROR_MALFORMED;
+ if (srcOffset + nalLength > size) {
+ mBuffer->release();
+ mBuffer = NULL;
+
+ return ERROR_MALFORMED;
+ }
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ CHECK(dstOffset + 4 <= mBuffer->size());
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
}
-
- if (nalLength == 0) {
- continue;
- }
-
- CHECK(dstOffset + 4 <= mBuffer->size());
-
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 1;
- memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
- srcOffset += nalLength;
- dstOffset += nalLength;
+ CHECK_EQ(srcOffset, size);
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, dstOffset);
}
- CHECK_EQ(srcOffset, size);
- CHECK(mBuffer != NULL);
- mBuffer->set_range(0, dstOffset);
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 8a5fb11..965c370 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -24,6 +24,7 @@
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
#include "include/MPEG2TSExtractor.h"
+#include "include/DRMExtractor.h"
#include "matroska/MatroskaExtractor.h"
@@ -63,6 +64,18 @@
mime, confidence);
}
+ if (!strncmp(mime, "drm", 3)) {
+ const char *originalMime = strrchr(mime, '+') + 1;
+
+ if (!strncmp(mime, "drm+es_based", 12)) {
+ return new DRMExtractor(source, originalMime);
+ } else if (!strncmp(mime, "drm+container_based", 19)) {
+ mime = originalMime;
+ } else {
+ return NULL;
+ }
+ }
+
if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
|| !strcasecmp(mime, "audio/mp4")) {
return new MPEG4Extractor(source);
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index 6bf6979..04cca47 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -42,7 +42,7 @@
path->setTo(slashPos);
}
- char *colonPos = strchr(host->string(), ':');
+ const char *colonPos = strchr(host->string(), ':');
if (colonPos != NULL) {
unsigned long x;
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 1629e9f..8426ee7 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -127,10 +127,11 @@
|| !strcasecmp(extension, ".rtttl")
|| !strcasecmp(extension, ".rtx")
|| !strcasecmp(extension, ".ota")) {
- return HandleMIDI(path, &client);
- }
-
- if (mRetriever->setDataSource(path) == OK
+ status_t status = HandleMIDI(path, &client);
+ if (status != OK) {
+ return status;
+ }
+ } else if (mRetriever->setDataSource(path) == OK
&& mRetriever->setMode(
METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) {
const char *value;
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index a68c641..90f3d6d 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -96,7 +96,7 @@
out->setTo(baseURL);
out->append(url);
} else {
- char *slashPos = strrchr(baseURL, '/');
+ const char *slashPos = strrchr(baseURL, '/');
if (slashPos > &baseURL[6]) {
out->setTo(baseURL, slashPos - baseURL);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index c059e60..e352928 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -26,6 +26,7 @@
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/TimeSource.h>
#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
namespace android {
@@ -41,6 +42,9 @@
struct ARTPSession;
struct UDPPusher;
+class DrmManagerClinet;
+class DecryptHandle;
+
struct AwesomeRenderer : public RefBase {
AwesomeRenderer() {}
@@ -216,6 +220,9 @@
}
} *mSuspensionState;
+ DrmManagerClient *mDrmManagerClient;
+ DecryptHandle *mDecryptHandle;
+
status_t setDataSource_l(
const char *uri,
const KeyedVector<String8, String8> *headers = NULL);
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
new file mode 100644
index 0000000..cafc812
--- /dev/null
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 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_EXTRACTOR_H_
+
+#define DRM_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+struct AMessage;
+class DataSource;
+class SampleTable;
+class String8;
+class DecryptHandle;
+
+class DRMExtractor : public MediaExtractor {
+public:
+ DRMExtractor(const sp<DataSource> &source, const char *mime);
+
+ virtual size_t countTracks();
+ virtual sp<MediaSource> getTrack(size_t index);
+ virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+ virtual sp<MetaData> getMetaData();
+
+protected:
+ virtual ~DRMExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+
+ sp<MediaExtractor> mOriginalExtractor;
+ DecryptHandle* mDecryptHandle;
+
+ DRMExtractor(const DRMExtractor &);
+ DRMExtractor &operator=(const DRMExtractor &);
+};
+
+bool SniffDRM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // DRM_EXTRACTOR_H_
+
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 2610b0e..bc2e4dc 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -39,6 +39,10 @@
virtual sp<MetaData> getMetaData();
+ // for DRM
+ virtual void setDrmFlag(bool flag);
+ virtual char* getDrmTrackInfo(size_t trackID, int *len);
+
protected:
virtual ~MPEG4Extractor();
@@ -71,6 +75,19 @@
static status_t verifyTrack(Track *track);
+ struct SINF {
+ SINF *next;
+ uint16_t trackID;
+ uint8_t IPMPDescriptorID;
+ ssize_t len;
+ char *IPMPData;
+ };
+
+ SINF *mFirstSINF;
+
+ bool mIsDrm;
+ status_t parseDrmSINF(off_t *offset, off_t data_offset);
+
status_t parseTrackHeader(off_t data_offset, off_t data_size);
MPEG4Extractor(const MPEG4Extractor &);
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 5ec03b2..f928c06 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -133,7 +133,7 @@
path->setTo(slashPos);
}
- char *colonPos = strchr(host->c_str(), ':');
+ const char *colonPos = strchr(host->c_str(), ':');
if (colonPos != NULL) {
unsigned long x;
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 0db3595..612caff 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -187,7 +187,7 @@
AString format;
getFormat(index, &format);
- char *lastSpacePos = strrchr(format.c_str(), ' ');
+ const char *lastSpacePos = strrchr(format.c_str(), ' ');
CHECK(lastSpacePos != NULL);
char *end;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 1bc9925..6943608 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1112,7 +1112,7 @@
out->setTo(baseURL);
out->append(url);
} else {
- char *slashPos = strrchr(baseURL, '/');
+ const char *slashPos = strrchr(baseURL, '/');
if (slashPos > &baseURL[6]) {
out->setTo(baseURL, slashPos - baseURL);