am 24a90c26: am d9334934: Merge "Update of DRM Framework."

* commit '24a90c2674270fee0783bafa54fd5d845bdf0c18':
  Update of DRM Framework.
diff --git a/api/current.xml b/api/current.xml
index cc044bc..2d190b5 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -70702,17 +70702,6 @@
 <parameter name="message" type="java.lang.String">
 </parameter>
 </constructor>
-<field name="TYPE_DRM_INFO_ACQUISITION_FAILED"
- type="int"
- transient="false"
- volatile="false"
- value="2008"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="TYPE_NOT_SUPPORTED"
  type="int"
  transient="false"
@@ -70846,17 +70835,6 @@
  visibility="public"
 >
 </method>
-<field name="DRM_INFO_OBJECT"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;drm_info_object&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="DRM_INFO_STATUS_OBJECT"
  type="java.lang.String"
  transient="false"
@@ -70879,17 +70857,6 @@
  visibility="public"
 >
 </field>
-<field name="TYPE_DRM_INFO_ACQUIRED"
- type="int"
- transient="false"
- volatile="false"
- value="1003"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="TYPE_DRM_INFO_PROCESSED"
  type="int"
  transient="false"
@@ -71365,6 +71332,19 @@
 </parameter>
 </constructor>
 <method name="acquireDrmInfo"
+ return="android.drm.DrmInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="drmInfoRequest" type="android.drm.DrmInfoRequest">
+</parameter>
+</method>
+<method name="acquireRights"
  return="int"
  abstract="false"
  native="false"
@@ -71562,6 +71542,32 @@
 <parameter name="mimeType" type="java.lang.String">
 </parameter>
 </method>
+<method name="getMetadata"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</method>
+<method name="getMetadata"
+ return="android.content.ContentValues"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
 <method name="getOriginalMimeType"
  return="java.lang.String"
  abstract="false"
diff --git a/drm/common/Android.mk b/drm/common/Android.mk
index 808b2c2..c79a91a 100644
--- a/drm/common/Android.mk
+++ b/drm/common/Android.mk
@@ -18,6 +18,7 @@
 
 LOCAL_SRC_FILES:= \
     DrmConstraints.cpp \
+    DrmMetadata.cpp \
     DrmConvertedStatus.cpp \
     DrmEngineBase.cpp \
     DrmInfo.cpp \
diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp
index 98a9ece..9b16c36 100644
--- a/drm/common/DrmEngineBase.cpp
+++ b/drm/common/DrmEngineBase.cpp
@@ -31,6 +31,10 @@
     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);
 }
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/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index fca4261..75edac6 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -24,6 +24,7 @@
 
 #include <drm/DrmInfo.h>
 #include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
 #include <drm/DrmRights.h>
 #include <drm/DrmInfoStatus.h>
 #include <drm/DrmConvertedStatus.h>
@@ -123,6 +124,35 @@
     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;
@@ -825,6 +855,38 @@
         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");
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 8da8176..9a6f787 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -23,6 +23,7 @@
 #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>
@@ -148,6 +149,15 @@
     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);
 
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index efd7bae..0901a44 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -18,18 +18,50 @@
 #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() :
@@ -79,6 +111,11 @@
     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);
@@ -172,13 +209,21 @@
 DecryptHandle* DrmManagerService::openDecryptSession(
             int uniqueId, int fd, off64_t offset, off64_t length) {
     LOGV("Entering DrmManagerService::openDecryptSession");
-    return mDrmManager->openDecryptSession(uniqueId, fd, offset, length);
+    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");
-    return mDrmManager->openDecryptSession(uniqueId, uri);
+    if (isProtectedCallAllowed()) {
+        return mDrmManager->openDecryptSession(uniqueId, uri);
+    }
+
+    return NULL;
 }
 
 status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
diff --git a/drm/java/android/drm/DrmErrorEvent.java b/drm/java/android/drm/DrmErrorEvent.java
index 9294884..20fd8aa 100644
--- a/drm/java/android/drm/DrmErrorEvent.java
+++ b/drm/java/android/drm/DrmErrorEvent.java
@@ -53,11 +53,6 @@
      * associated with all DRM schemes.
      */
     public static final int TYPE_REMOVE_ALL_RIGHTS_FAILED = 2007;
-    /**
-     * TYPE_DRM_INFO_ACQUISITION_FAILED, when failed to get the required information to
-     * communicate with the service.
-     */
-    public static final int TYPE_DRM_INFO_ACQUISITION_FAILED = 2008;
 
     /**
      * constructor to create DrmErrorEvent object with given parameters
diff --git a/drm/java/android/drm/DrmEvent.java b/drm/java/android/drm/DrmEvent.java
index 583337f..f7bc5cd 100644
--- a/drm/java/android/drm/DrmEvent.java
+++ b/drm/java/android/drm/DrmEvent.java
@@ -31,14 +31,8 @@
      * Constant field signifies that given information is processed successfully
      */
     public static final int TYPE_DRM_INFO_PROCESSED = 1002;
-    /**
-     * Constant field signifies that the required information to communicate with
-     * the service is acquired sucessfully
-     */
-    public static final int TYPE_DRM_INFO_ACQUIRED = 1003;
 
     public static final String DRM_INFO_STATUS_OBJECT = "drm_info_status_object";
-    public static final String DRM_INFO_OBJECT = "drm_info_object";
 
     private final int mUniqueId;
     private final int mType;
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 5044d36..2f54b33 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -102,8 +102,7 @@
     }
 
     private static final int ACTION_REMOVE_ALL_RIGHTS = 1001;
-    private static final int ACTION_ACQUIRE_DRM_INFO = 1002;
-    private static final int ACTION_PROCESS_DRM_INFO = 1003;
+    private static final int ACTION_PROCESS_DRM_INFO = 1002;
 
     private int mUniqueId;
     private int mNativeContext;
@@ -126,18 +125,6 @@
             HashMap<String, Object> attributes = new HashMap<String, Object>();
 
             switch(msg.what) {
-            case ACTION_ACQUIRE_DRM_INFO: {
-                final DrmInfoRequest request = (DrmInfoRequest) msg.obj;
-                DrmInfo drmInfo = _acquireDrmInfo(mUniqueId, request);
-                if (null != drmInfo) {
-                    attributes.put(DrmEvent.DRM_INFO_OBJECT, drmInfo);
-                    event = new DrmEvent(mUniqueId, DrmEvent.TYPE_DRM_INFO_ACQUIRED, null);
-                } else {
-                    error = new DrmErrorEvent(mUniqueId,
-                            DrmErrorEvent.TYPE_DRM_INFO_ACQUISITION_FAILED, null);
-                }
-                break;
-            }
             case ACTION_PROCESS_DRM_INFO: {
                 final DrmInfo drmInfo = (DrmInfo) msg.obj;
                 DrmInfoStatus status = _processDrmInfo(mUniqueId, drmInfo);
@@ -243,19 +230,14 @@
      */
     public DrmManagerClient(Context context) {
         mContext = context;
-        Looper looper;
 
-        if (null != (looper = Looper.myLooper())) {
-            mInfoHandler = new InfoHandler(looper);
-        } else if (null != (looper = Looper.getMainLooper())) {
-            mInfoHandler = new InfoHandler(looper);
-        } else {
-            mInfoHandler = null;
-        }
+        HandlerThread infoThread = new HandlerThread("DrmManagerClient.InfoHandler");
+        infoThread.start();
+        mInfoHandler = new InfoHandler(infoThread.getLooper());
 
-        HandlerThread thread = new HandlerThread("DrmManagerClient.EventHandler");
-        thread.start();
-        mEventHandler = new EventHandler(thread.getLooper());
+        HandlerThread eventThread = new HandlerThread("DrmManagerClient.EventHandler");
+        eventThread.start();
+        mEventHandler = new EventHandler(eventThread.getLooper());
 
         // save the unique id
         mUniqueId = hashCode();
@@ -335,10 +317,24 @@
         return _getConstraints(mUniqueId, path, action);
     }
 
+   /**
+    * Get metadata information from DRM content
+    *
+    * @param path Content path from where DRM metadata would be retrieved.
+    * @return ContentValues instance in which metadata key-value pairs are embedded
+    *         or null in case of failure
+    */
+    public ContentValues getMetadata(String path) {
+        if (null == path || path.equals("")) {
+            throw new IllegalArgumentException("Given path is invalid/null");
+        }
+        return _getMetadata(mUniqueId, path);
+    }
+
     /**
      * Get constraints information evaluated from DRM content
      *
-     * @param uri The Content URI of the data
+     * @param uri Content URI from where DRM constraints would be retrieved.
      * @param action Actions defined in {@link DrmStore.Action}
      * @return ContentValues instance in which constraints key-value pairs are embedded
      *         or null in case of failure
@@ -350,6 +346,20 @@
         return getConstraints(convertUriToPath(uri), action);
     }
 
+   /**
+    * Get metadata information from DRM content
+    *
+    * @param uri Content URI from where DRM metadata would be retrieved.
+    * @return ContentValues instance in which metadata key-value pairs are embedded
+    *         or null in case of failure
+    */
+    public ContentValues getMetadata(Uri uri) {
+        if (null == uri || Uri.EMPTY == uri) {
+            throw new IllegalArgumentException("Uri should be non null");
+        }
+        return getMetadata(convertUriToPath(uri));
+    }
+
     /**
      * Save DRM rights to specified rights path
      * and make association with content path.
@@ -408,7 +418,7 @@
     /**
      * Check whether the given mimetype or uri can be handled.
      *
-     * @param uri The content URI of the data
+     * @param uri Content URI of the data to be handled.
      * @param mimeType Mimetype of the object to be handled
      * @return
      *        true - if the given mimeType or path can be handled
@@ -445,20 +455,31 @@
      * Retrieves necessary information for register, unregister or rights acquisition.
      *
      * @param drmInfoRequest Request information to retrieve drmInfo
+     * @return DrmInfo Instance as a result of processing given input
+     */
+    public DrmInfo acquireDrmInfo(DrmInfoRequest drmInfoRequest) {
+        if (null == drmInfoRequest || !drmInfoRequest.isValid()) {
+            throw new IllegalArgumentException("Given drmInfoRequest is invalid/null");
+        }
+        return _acquireDrmInfo(mUniqueId, drmInfoRequest);
+    }
+
+    /**
+     * Executes given DrmInfoRequest and returns the rights information asynchronously.
+     * This is a utility API which consists of {@link #acquireDrmInfo(DrmInfoRequest)}
+     * and {@link #processDrmInfo(DrmInfo)}.
+     * It can be used if selected DRM agent can work with this combined sequences.
+     * In case of some DRM schemes, such as OMA DRM, application needs to invoke
+     * {@link #acquireDrmInfo(DrmInfoRequest)} and {@link #processDrmInfo(DrmInfo)}, separately.
+     *
+     * @param drmInfoRequest Request information to retrieve drmInfo
      * @return
      *     ERROR_NONE for success
      *     ERROR_UNKNOWN for failure
      */
-    public int acquireDrmInfo(DrmInfoRequest drmInfoRequest) {
-        if (null == drmInfoRequest || !drmInfoRequest.isValid()) {
-            throw new IllegalArgumentException("Given drmInfoRequest is invalid/null");
-        }
-        int result = ERROR_UNKNOWN;
-        if (null != mEventHandler) {
-            Message msg = mEventHandler.obtainMessage(ACTION_ACQUIRE_DRM_INFO, drmInfoRequest);
-            result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
-        }
-        return result;
+    public int acquireRights(DrmInfoRequest drmInfoRequest) {
+        DrmInfo drmInfo = acquireDrmInfo(drmInfoRequest);
+        return processDrmInfo(drmInfo);
     }
 
     /**
@@ -750,6 +771,8 @@
 
     private native ContentValues _getConstraints(int uniqueId, String path, int usage);
 
+    private native ContentValues _getMetadata(int uniqueId, String path);
+
     private native boolean _canHandle(int uniqueId, String path, String mimeType);
 
     private native DrmInfoStatus _processDrmInfo(int uniqueId, DrmInfo drmInfo);
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index e5e4547..e131839 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -29,6 +29,7 @@
 #include <drm/DrmInfoRequest.h>
 #include <drm/DrmSupportInfo.h>
 #include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
 #include <drm/DrmConvertedStatus.h>
 #include <drm/drm_framework_common.h>
 
@@ -298,6 +299,43 @@
     return constraints;
 }
 
+static jobject android_drm_DrmManagerClient_getMetadataFromContent(
+            JNIEnv* env, jobject thiz, jint uniqueId, jstring jpath) {
+    LOGV("GetMetadata - Enter");
+    const String8 pathString = Utility::getStringValue(env, jpath);
+    DrmMetadata* pMetadata =
+            getDrmManagerClientImpl(env, thiz)->getMetadata(uniqueId, &pathString);
+
+    jobject metadata = NULL;
+
+    jclass localRef = NULL;
+    localRef = env->FindClass("android/content/ContentValues");
+    if (NULL != localRef && NULL != pMetadata) {
+        // Get the constructor id
+        jmethodID constructorId = NULL;
+        constructorId = env->GetMethodID(localRef, "<init>", "()V");
+        if (NULL != constructorId) {
+            // create the java DrmMetadata object
+            metadata = env->NewObject(localRef, constructorId);
+            if (NULL != metadata) {
+                DrmMetadata::KeyIterator keyIt = pMetadata->keyIterator();
+                while (keyIt.hasNext()) {
+                    String8 key = keyIt.next();
+                    // insert the entry<constraintKey, constraintValue>
+                    // to newly created java object
+                    String8 value = pMetadata->get(key);
+                    env->CallVoidMethod(metadata, env->GetMethodID(localRef, "put",
+                            "(Ljava/lang/String;Ljava/lang/String;)V"),
+                    env->NewStringUTF(key.string()), env->NewStringUTF(value.string()));
+                }
+            }
+        }
+    }
+    delete pMetadata; pMetadata = NULL;
+    LOGV("GetMetadata - Exit");
+    return metadata;
+}
+
 static jobjectArray android_drm_DrmManagerClient_getAllSupportInfo(
             JNIEnv* env, jobject thiz, jint uniqueId) {
     LOGV("GetAllSupportInfo - Enter");
@@ -682,6 +720,9 @@
     {"_getConstraints", "(ILjava/lang/String;I)Landroid/content/ContentValues;",
                                     (void*)android_drm_DrmManagerClient_getConstraintsFromContent},
 
+    {"_getMetadata", "(ILjava/lang/String;)Landroid/content/ContentValues;",
+                                    (void*)android_drm_DrmManagerClient_getMetadataFromContent},
+
     {"_getAllSupportInfo", "(I)[Landroid/drm/DrmSupportInfo;",
                                     (void*)android_drm_DrmManagerClient_getAllSupportInfo},
 
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index 0cbbbd4..578e135 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -43,6 +43,10 @@
     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);
 }
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index 519ed67..f39131d 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -101,6 +101,14 @@
     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)) {
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index a0250b7..e05366d 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -32,6 +32,7 @@
 class DrmRightsAcquisitionInfo;
 class DrmContentIds;
 class DrmConstraints;
+class DrmMetadata;
 class DrmRights;
 class DrmInfo;
 class DrmInfoStatus;
@@ -74,6 +75,8 @@
 
     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);
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 769f4d0..0a7fcd1 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -86,6 +86,18 @@
     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
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index 4b3ba71..d0a0db7 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -61,6 +61,8 @@
 
     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);
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 20fb2ab..2424ea5 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -27,6 +27,7 @@
 
 class DrmContentIds;
 class DrmConstraints;
+class DrmMetadata;
 class DrmRights;
 class DrmInfo;
 class DrmInfoStatus;
@@ -51,6 +52,7 @@
         SET_DRM_SERVICE_LISTENER,
         INSTALL_DRM_ENGINE,
         GET_CONSTRAINTS_FROM_CONTENT,
+        GET_METADATA_FROM_CONTENT,
         CAN_HANDLE,
         PROCESS_DRM_INFO,
         ACQUIRE_DRM_INFO,
@@ -96,6 +98,8 @@
     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;
@@ -179,6 +183,8 @@
 
     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);
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index 779f7ac..b61e3d3 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -36,6 +36,8 @@
 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);
@@ -117,6 +119,18 @@
             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
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
index 28e6d8e..d05c24f 100644
--- a/drm/libdrmframework/plugins/common/include/IDrmEngine.h
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -23,6 +23,7 @@
 
 class DrmContentIds;
 class DrmConstraints;
+class DrmMetadata;
 class DrmRights;
 class DrmInfo;
 class DrmInfoStatus;
@@ -105,6 +106,18 @@
             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
diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
index 9c94e73..f941f70 100644
--- a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
+++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
@@ -30,6 +30,8 @@
 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);
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
index 73c9708..976978f 100644
--- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -20,6 +20,7 @@
 
 #include <drm/DrmRights.h>
 #include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
 #include <drm/DrmInfo.h>
 #include <drm/DrmInfoEvent.h>
 #include <drm/DrmInfoStatus.h>
@@ -51,6 +52,10 @@
 
 }
 
+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);
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
index 782ebae..e6ba3c4 100644
--- a/include/drm/DrmManagerClient.h
+++ b/include/drm/DrmManagerClient.h
@@ -25,6 +25,7 @@
 
 class DrmInfo;
 class DrmRights;
+class DrmMetadata;
 class DrmInfoEvent;
 class DrmInfoStatus;
 class DrmInfoRequest;
@@ -204,6 +205,17 @@
     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
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__ */
+