Initial contribution from Sony Corporation.

  Add DRM Framework to support DRM content playback
  together with StageFright.

  - DRM Framework code is added
     - include/drm
     - drm
  - api/current.xml is updated to include DRM Framework Java APIs
  - cmds/servicemanager/service_manager.c is modified
    to add drmManager and drmIOService.

Change-Id: I6d7bc9c7067362b500e530988a9ce241761866fb
diff --git a/drm/common/Android.mk b/drm/common/Android.mk
new file mode 100644
index 0000000..249fe8e
--- /dev/null
+++ b/drm/common/Android.mk
@@ -0,0 +1,41 @@
+#
+# 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 \
+    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
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/common/DrmConstraints.cpp b/drm/common/DrmConstraints.cpp
new file mode 100644
index 0000000..11ce410
--- /dev/null
+++ b/drm/common/DrmConstraints.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/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) {
+    LOGV("DrmConstraints::KeyIterator::KeyIterator");
+}
+
+DrmConstraints::KeyIterator& DrmConstraints::KeyIterator::operator=(
+    const DrmConstraints::KeyIterator& keyIterator) {
+    LOGV("DrmConstraints::KeyIterator::operator=");
+    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) {
+    LOGV("DrmConstraints::Iterator::Iterator");
+}
+
+DrmConstraints::Iterator& DrmConstraints::Iterator::operator=(
+    const DrmConstraints::Iterator& iterator) {
+    LOGV("DrmConstraints::Iterator::operator=");
+    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..70398e8
--- /dev/null
+++ b/drm/common/DrmEngineBase.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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);
+}
+
+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);
+}
+
+void 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);
+}
+
+void DrmEngineBase::consumeRights(
+    int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+    onConsumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+void DrmEngineBase::setPlaybackStatus(
+    int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+    onSetPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmEngineBase::validateAction(
+    int uniqueId, const String8& path,
+    int action, const ActionDescription& description) {
+    return onValidateAction(uniqueId, path, action, description);
+}
+
+void DrmEngineBase::removeRights(int uniqueId, const String8& path) {
+    onRemoveRights(uniqueId, path);
+}
+
+void DrmEngineBase::removeAllRights(int uniqueId) {
+    onRemoveAllRights(uniqueId);
+}
+
+void DrmEngineBase::openConvertSession(int uniqueId, int convertId) {
+    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);
+}
+
+void DrmEngineBase::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+    onCloseDecryptSession(uniqueId, decryptHandle);
+}
+
+void DrmEngineBase::initializeDecryptUnit(
+    int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+    onInitializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmEngineBase::decrypt(
+    int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+    const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+    return onDecrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer);
+}
+
+void DrmEngineBase::finalizeDecryptUnit(
+    int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+    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..eb58129
--- /dev/null
+++ b/drm/common/DrmInfoEvent.cpp
@@ -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.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "DrmInfoEvent"
+#include "utils/Log.h"
+
+#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..f3a1516
--- /dev/null
+++ b/drm/common/DrmInfoStatus.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/DrmInfoStatus.h>
+
+using namespace android;
+
+DrmInfoStatus::DrmInfoStatus(
+    int _statusCode, const DrmBuffer* _drmBuffer, const String8& _mimeType) :
+    statusCode(_statusCode),
+    drmBuffer(_drmBuffer),
+    mimeType(_mimeType) {
+
+}
+
diff --git a/drm/common/DrmRights.cpp b/drm/common/DrmRights.cpp
new file mode 100644
index 0000000..dc1e6c5
--- /dev/null
+++ b/drm/common/DrmRights.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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>
+
+using namespace android;
+
+DrmRights::DrmRights(const String8& rightsFilePath, const String8& mimeType,
+            const String8& accountId, const String8& subscriptionId) {
+    /**
+     * TODO Read DrmRights from rights file
+     */
+}
+
+DrmRights::DrmRights(const DrmBuffer& rightsData, const String8& mimeType,
+            const String8& accountId, const String8& subscriptionId) :
+    mData(rightsData),
+    mMimeType(mimeType),
+    mAccountId(accountId),
+    mSubscriptionId(subscriptionId) {
+}
+
+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..35e83fc
--- /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 (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 (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..7ce45e7
--- /dev/null
+++ b/drm/common/IDrmIOService.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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 "IDrmIOService"
+#include <utils/Log.h>
+
+#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..4fc828a
--- /dev/null
+++ b/drm/common/IDrmManagerService.cpp
@@ -0,0 +1,1358 @@
+/*
+ * 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/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;
+
+status_t BpDrmManagerService::loadPlugIns(int uniqueId) {
+    LOGV("load plugins");
+    Parcel data, reply;
+
+    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+    data.writeInt32(uniqueId);
+
+    remote()->transact(LOAD_PLUGINS, data, &reply);
+    return reply.readInt32();
+}
+
+status_t BpDrmManagerService::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
+    LOGV("load plugins from path");
+    Parcel data, reply;
+
+    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+    data.writeInt32(uniqueId);
+    data.writeString8(plugInDirPath);
+
+    remote()->transact(LOAD_PLUGINS_FROM_PATH, data, &reply);
+    return reply.readInt32();
+}
+
+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::unloadPlugIns(int uniqueId) {
+    LOGV("unload plugins");
+    Parcel data, reply;
+
+    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+    data.writeInt32(uniqueId);
+
+    remote()->transact(UNLOAD_PLUGINS, 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;
+}
+
+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 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, 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;
+}
+
+void 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);
+}
+
+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();
+}
+
+void 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);
+}
+
+void 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);
+}
+
+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());
+}
+
+void 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);
+}
+
+void BpDrmManagerService::removeAllRights(int uniqueId) {
+    LOGV("removeAllRights");
+    Parcel data, reply;
+
+    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+    data.writeInt32(uniqueId);
+
+    remote()->transact(REMOVE_ALL_RIGHTS, data, &reply);
+}
+
+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;
+
+    const String16 interfaceDescriptor = IDrmManagerService::getInterfaceDescriptor();
+    LOGV("BpDrmManagerService::openDecryptSession: InterfaceDescriptor name is %s",
+        interfaceDescriptor.string());
+    data.writeInterfaceToken(interfaceDescriptor);
+    data.writeInt32(uniqueId);
+    data.writeFileDescriptor(fd);
+    data.writeInt32(offset);
+    data.writeInt32(length);
+
+    LOGV("try to invoke remote onTransact() with code OPEN_DECRYPT_SESSION");
+    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;
+}
+
+void 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;
+}
+
+void 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);
+}
+
+status_t BpDrmManagerService::decrypt(
+            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+            const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+    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);
+
+    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;
+}
+
+void 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);
+}
+
+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 LOAD_PLUGINS:
+    {
+        LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS");
+        CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+        status_t status = loadPlugIns(data.readInt32());
+
+        reply->writeInt32(status);
+        return DRM_NO_ERROR;
+
+    }
+
+    case LOAD_PLUGINS_FROM_PATH:
+    {
+        LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS_FROM_PATH");
+        CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+        status_t status = loadPlugIns(data.readInt32(), data.readString8());
+
+        reply->writeInt32(status);
+        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 UNLOAD_PLUGINS:
+    {
+        LOGV("BnDrmManagerService::onTransact :UNLOAD_PLUGINS");
+        CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+        status_t status = unloadPlugIns(data.readInt32());
+
+        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 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->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));
+
+        saveRights(uniqueId, drmRights,
+                            ((rightsPath == String8("NULL")) ? String8("") : rightsPath),
+                            ((contentPath == String8("NULL")) ? String8("") : contentPath));
+
+        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;
+        }
+
+        consumeRights(uniqueId, &handle, data.readInt32(), static_cast<bool>(data.readInt32()));
+
+        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;
+        }
+
+        setPlaybackStatus(uniqueId, &handle, data.readInt32(), data.readInt32());
+
+        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);
+
+        removeRights(data.readInt32(), data.readString8());
+
+        return DRM_NO_ERROR;
+    }
+
+    case REMOVE_ALL_RIGHTS:
+    {
+        LOGV("BnDrmManagerService::onTransact :REMOVE_ALL_RIGHTS");
+        CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+        removeAllRights(data.readInt32());
+
+        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 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;
+        }
+
+        closeDecryptSession(uniqueId, handle);
+        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);
+
+        initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo);
+
+        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);
+
+        const status_t status = decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer);
+
+        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;
+        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;
+        }
+
+        finalizeDecryptUnit(uniqueId, &handle, data.readInt32());
+
+        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..0a69115
--- /dev/null
+++ b/drm/common/IDrmServiceListener.cpp
@@ -0,0 +1,65 @@
+/*
+ * 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 "IDrmServiceListener"
+#include <utils/Log.h>
+
+#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..4319c1c
--- /dev/null
+++ b/drm/common/ReadWriteUtils.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 <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/FileMap.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) {
+            FileMap* fileMap = new FileMap();
+            if (fileMap->create(filePath.string(), fd, 0, sb.st_size, true)) {
+                char* addr = (char*)fileMap->getDataPtr();
+                string.append(addr, sb.st_size);
+                fileMap->release();
+            }
+        }
+        fclose(file);
+    }
+    return string;
+}
+
+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)) {
+            FileMap* fileMap = NULL;
+            fileMap = new FileMap();
+            if (fileMap->create(filePath.string(), fd, 0, size, false)) {
+                char* addr = (char*)fileMap->getDataPtr();
+                memcpy(addr, data.string(), size);
+                fileMap->release();
+            }
+        }
+        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 offset = lseek(fd, 0, SEEK_END);
+        if (FAILURE != offset) {
+            int newEntrySize = data.size();
+            int fileSize = offset + newEntrySize;
+
+            if (FAILURE != ftruncate(fd, fileSize)) {
+                FileMap* fileMap = NULL;
+                fileMap = new FileMap();
+                if (fileMap->create(filePath.string(), fd, offset, fileSize, false)) {
+                    char* addr = (char*)fileMap->getDataPtr();
+                    memcpy(addr, data.string(), data.size());
+                    fileMap->release();
+                }
+            }
+        }
+        fclose(file);
+    }
+}
+