Merge "Release reference when putting RILRequest back into the pool."
diff --git a/api/current.xml b/api/current.xml
index 19bef42..7dc498d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -55246,6 +55246,29 @@
 </parameter>
 <parameter name="selection" type="java.lang.String">
 </parameter>
+<parameter name="groupBy" type="java.lang.String">
+</parameter>
+<parameter name="having" type="java.lang.String">
+</parameter>
+<parameter name="sortOrder" type="java.lang.String">
+</parameter>
+<parameter name="limit" type="java.lang.String">
+</parameter>
+</method>
+<method name="buildQuery"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="projectionIn" type="java.lang.String[]">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 <parameter name="groupBy" type="java.lang.String">
@@ -55323,6 +55346,33 @@
 </parameter>
 <parameter name="selection" type="java.lang.String">
 </parameter>
+<parameter name="groupBy" type="java.lang.String">
+</parameter>
+<parameter name="having" type="java.lang.String">
+</parameter>
+</method>
+<method name="buildUnionSubQuery"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="typeDiscriminatorColumn" type="java.lang.String">
+</parameter>
+<parameter name="unionColumns" type="java.lang.String[]">
+</parameter>
+<parameter name="columnsPresentInTable" type="java.util.Set&lt;java.lang.String&gt;">
+</parameter>
+<parameter name="computedColumnsOffset" type="int">
+</parameter>
+<parameter name="typeDiscriminatorValue" type="java.lang.String">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 <parameter name="groupBy" type="java.lang.String">
@@ -55656,29 +55706,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="2012"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TYPE_FINALIZE_FAILED"
- type="int"
- transient="false"
- volatile="false"
- value="2010"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TYPE_INITIALIZE_FAILED"
- type="int"
- transient="false"
- volatile="false"
- value="2009"
+ value="2008"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -55718,7 +55746,7 @@
  visibility="public"
 >
 </field>
-<field name="TYPE_REGISTRATION_FAILED"
+<field name="TYPE_PROCESS_DRM_INFO_FAILED"
  type="int"
  transient="false"
  volatile="false"
@@ -55733,18 +55761,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="2011"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TYPE_RIGHTS_ACQUISITION_FAILED"
- type="int"
- transient="false"
- volatile="false"
- value="2008"
+ value="2007"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -55773,17 +55790,6 @@
  visibility="public"
 >
 </field>
-<field name="TYPE_UNREGISTRATION_FAILED"
- type="int"
- transient="false"
- volatile="false"
- value="2007"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <class name="DrmEvent"
  extends="java.lang.Object"
@@ -55866,7 +55872,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="1006"
+ value="1001"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -55877,28 +55883,6 @@
  type="int"
  transient="false"
  volatile="false"
- value="1007"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TYPE_FINALIZED"
- type="int"
- transient="false"
- volatile="false"
- value="1001"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TYPE_INITIALIZED"
- type="int"
- transient="false"
- volatile="false"
  value="1003"
  static="true"
  final="true"
@@ -55906,7 +55890,7 @@
  visibility="public"
 >
 </field>
-<field name="TYPE_REGISTERED"
+<field name="TYPE_DRM_INFO_PROCESSED"
  type="int"
  transient="false"
  volatile="false"
@@ -55917,28 +55901,6 @@
  visibility="public"
 >
 </field>
-<field name="TYPE_RIGHTS_ACQUIRED"
- type="int"
- transient="false"
- volatile="false"
- value="1005"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="TYPE_UNREGISTERED"
- type="int"
- transient="false"
- volatile="false"
- value="1004"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <class name="DrmInfo"
  extends="java.lang.Object"
@@ -56314,6 +56276,8 @@
 >
 <parameter name="_statusCode" type="int">
 </parameter>
+<parameter name="_infoType" type="int">
+</parameter>
 <parameter name="_data" type="android.drm.ProcessedData">
 </parameter>
 <parameter name="_mimeType" type="java.lang.String">
@@ -56351,6 +56315,16 @@
  visibility="public"
 >
 </field>
+<field name="infoType"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="mimeType"
  type="java.lang.String"
  transient="false"
@@ -56614,17 +56588,6 @@
 <parameter name="uri" type="android.net.Uri">
 </parameter>
 </method>
-<method name="loadPlugIns"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="openConvertSession"
  return="int"
  abstract="false"
@@ -56746,17 +56709,6 @@
 <parameter name="infoListener" type="android.drm.DrmManagerClient.OnInfoListener">
 </parameter>
 </method>
-<method name="unloadPlugIns"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <field name="ERROR_NONE"
  type="int"
  transient="false"
@@ -216266,7 +216218,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index f4b48b6..12c9fe5 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -248,13 +248,11 @@
     mFlingerSurface = s;
 
     mAndroidAnimation = true;
-    if ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) ||
-        (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0)) {
-        if ((mZip.open(USER_BOOTANIMATION_FILE) != NO_ERROR) ||
-            (mZip.open(SYSTEM_BOOTANIMATION_FILE) != NO_ERROR)) {
-            mAndroidAnimation = false;
-        }
-    }
+    if ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&
+            (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR) ||
+            (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
+            (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))
+        mAndroidAnimation = false;
 
     return NO_ERROR;
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 6fe12fc..2b42f8c 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -38,13 +38,17 @@
  * </ul>
  *
  * <p>
- * Each of the notify methods takes an int id parameter.  This id identifies
- * this notification from your app to the system, so that id should be unique
- * within your app.  If you call one of the notify methods with an id that is
- * currently active and a new set of notification parameters, it will be
- * updated.  For example, if you pass a new status bar icon, the old icon in
- * the status bar will be replaced with the new one.  This is also the same
- * id you pass to the {@link #cancel} method to clear this notification.
+ * Each of the notify methods takes an int id parameter and optionally a
+ * {@link String} tag parameter, which may be {@code null}.  These parameters
+ * are used to form a pair (tag, id), or ({@code null}, id) if tag is
+ * unspecified.  This pair identifies this notification from your app to the
+ * system, so that pair should be unique within your app.  If you call one
+ * of the notify methods with a (tag, id) pair that is currently active and
+ * a new set of notification parameters, it will be updated.  For example,
+ * if you pass a new status bar icon, the old icon in the status bar will
+ * be replaced with the new one.  This is also the same tag and id you pass
+ * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
+ * this notification.
  *
  * <p>
  * You do not instantiate this class directly; instead, retrieve it through
@@ -93,12 +97,11 @@
     /**
      * Persistent notification on the status bar,
      *
-     * @param tag An string identifier for this notification unique within your
-     *        application.
+     * @param tag A string identifier for this notification.  May be {@code null}.
+     * @param id An identifier for this notification.  The pair (tag, id) must be unique
+     *        within your application.
      * @param notification A {@link Notification} object describing how to
      *        notify the user, other than the view you're providing. Must not be null.
-     * @return the id of the notification that is associated with the string identifier that
-     * can be used to cancel the notification
      */
     public void notify(String tag, int id, Notification notification)
     {
diff --git a/core/java/android/content/UriMatcher.java b/core/java/android/content/UriMatcher.java
index 72ec469..841c8f4 100644
--- a/core/java/android/content/UriMatcher.java
+++ b/core/java/android/content/UriMatcher.java
@@ -25,8 +25,8 @@
 /**
 Utility class to aid in matching URIs in content providers.
 
-<p>To use this class, build up a tree of UriMatcher objects.
-Typically, it looks something like this:
+<p>To use this class, build up a tree of <code>UriMatcher</code> objects.
+For example:
 <pre>
     private static final int PEOPLE = 1;
     private static final int PEOPLE_ID = 2;
@@ -48,36 +48,35 @@
     private static final int CALLS_ID = 12;
     private static final int CALLS_FILTER = 15;
 
-    private static final UriMatcher sURIMatcher = new UriMatcher();
+    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
     static
     {
-        sURIMatcher.addURI("contacts", "/people", PEOPLE);
-        sURIMatcher.addURI("contacts", "/people/#", PEOPLE_ID);
-        sURIMatcher.addURI("contacts", "/people/#/phones", PEOPLE_PHONES);
-        sURIMatcher.addURI("contacts", "/people/#/phones/#", PEOPLE_PHONES_ID);
-        sURIMatcher.addURI("contacts", "/people/#/contact_methods", PEOPLE_CONTACTMETHODS);
-        sURIMatcher.addURI("contacts", "/people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
-        sURIMatcher.addURI("contacts", "/deleted_people", DELETED_PEOPLE);
-        sURIMatcher.addURI("contacts", "/phones", PHONES);
-        sURIMatcher.addURI("contacts", "/phones/filter/*", PHONES_FILTER);
-        sURIMatcher.addURI("contacts", "/phones/#", PHONES_ID);
-        sURIMatcher.addURI("contacts", "/contact_methods", CONTACTMETHODS);
-        sURIMatcher.addURI("contacts", "/contact_methods/#", CONTACTMETHODS_ID);
-        sURIMatcher.addURI("call_log", "/calls", CALLS);
-        sURIMatcher.addURI("call_log", "/calls/filter/*", CALLS_FILTER);
-        sURIMatcher.addURI("call_log", "/calls/#", CALLS_ID);
+        sURIMatcher.addURI("contacts", "people", PEOPLE);
+        sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID);
+        sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES);
+        sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID);
+        sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS);
+        sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
+        sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE);
+        sURIMatcher.addURI("contacts", "phones", PHONES);
+        sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER);
+        sURIMatcher.addURI("contacts", "phones/#", PHONES_ID);
+        sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS);
+        sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID);
+        sURIMatcher.addURI("call_log", "calls", CALLS);
+        sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);
+        sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
     }
 </pre>
-<p>Then when you need to match match against a URI, call {@link #match}, providing
-the tokenized url you've been given, and the value you want if there isn't
-a match.  You can use the result to build a query, return a type, insert or
-delete a row, or whatever you need, without duplicating all of the if-else
-logic you'd otherwise need.  Like this:
+<p>Then when you need to match against a URI, call {@link #match}, providing
+the URL that you have been given.  You can use the result to build a query,
+return a type, insert or delete a row, or whatever you need, without duplicating
+all of the if-else logic that you would otherwise need.  For example:
 <pre>
-    public String getType(String[] url)
+    public String getType(Uri url)
     {
-        int match = sURIMatcher.match(url, NO_MATCH);
+        int match = sURIMatcher.match(url);
         switch (match)
         {
             case PEOPLE:
@@ -93,19 +92,20 @@
         }
     }
 </pre>
-instead of
+instead of:
 <pre>
-    public String getType(String[] url)
+    public String getType(Uri url)
     {
-        if (url.length >= 2) {
-            if (url[1].equals("people")) {
-                if (url.length == 2) {
+        List<String> pathSegments = url.getPathSegments();
+        if (pathSegments.size() >= 2) {
+            if ("people".equals(pathSegments.get(1))) {
+                if (pathSegments.size() == 2) {
                     return "vnd.android.cursor.dir/person";
-                } else if (url.length == 3) {
+                } else if (pathSegments.size() == 3) {
                     return "vnd.android.cursor.item/person";
 ... snip ...
                     return "vnd.android.cursor.dir/snail-mail";
-                } else if (url.length == 3) {
+                } else if (pathSegments.size() == 3) {
                     return "vnd.android.cursor.item/snail-mail";
                 }
             }
diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java
index 6539156..e339a63 100644
--- a/core/java/android/database/Cursor.java
+++ b/core/java/android/database/Cursor.java
@@ -211,7 +211,9 @@
     /**
      * Returns the value of the requested column as a byte array.
      *
-     * <p>If the native content of that column is not blob exception may throw
+     * <p>The result and whether this method throws an exception when the
+     * column value is null or the column type is not a blob type is
+     * implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as a byte array.
@@ -221,8 +223,9 @@
     /**
      * Returns the value of the requested column as a String.
      *
-     * <p>If the native content of that column is not text the result will be
-     * the result of passing the column value to String.valueOf(x).
+     * <p>The result and whether this method throws an exception when the
+     * column value is null or the column type is not a string type is
+     * implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as a String.
@@ -242,8 +245,10 @@
     /**
      * Returns the value of the requested column as a short.
      *
-     * <p>If the native content of that column is not numeric the result will be
-     * the result of passing the column value to Short.valueOf(x).
+     * <p>The result and whether this method throws an exception when the
+     * column value is null, the column type is not an integral type, or the
+     * integer value is outside the range [<code>Short.MIN_VALUE</code>,
+     * <code>Short.MAX_VALUE</code>] is implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as a short.
@@ -253,8 +258,10 @@
     /**
      * Returns the value of the requested column as an int.
      *
-     * <p>If the native content of that column is not numeric the result will be
-     * the result of passing the column value to Integer.valueOf(x).
+     * <p>The result and whether this method throws an exception when the
+     * column value is null, the column type is not an integral type, or the
+     * integer value is outside the range [<code>Integer.MIN_VALUE</code>,
+     * <code>Integer.MAX_VALUE</code>] is implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as an int.
@@ -264,8 +271,10 @@
     /**
      * Returns the value of the requested column as a long.
      *
-     * <p>If the native content of that column is not numeric the result will be
-     * the result of passing the column value to Long.valueOf(x).
+     * <p>The result and whether this method throws an exception when the
+     * column value is null, the column type is not an integral type, or the
+     * integer value is outside the range [<code>Long.MIN_VALUE</code>,
+     * <code>Long.MAX_VALUE</code>] is implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as a long.
@@ -275,8 +284,10 @@
     /**
      * Returns the value of the requested column as a float.
      *
-     * <p>If the native content of that column is not numeric the result will be
-     * the result of passing the column value to Float.valueOf(x).
+     * <p>The result and whether this method throws an exception when the
+     * column value is null, the column type is not a floating-point type, or the
+     * floating-point value is not representable as a <code>float</code> value is
+     * implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as a float.
@@ -286,8 +297,10 @@
     /**
      * Returns the value of the requested column as a double.
      *
-     * <p>If the native content of that column is not numeric the result will be
-     * the result of passing the column value to Double.valueOf(x).
+     * <p>The result and whether this method throws an exception when the
+     * column value is null, the column type is not a floating-point type, or the
+     * floating-point value is not representable as a <code>double</code> value is
+     * implementation-defined.
      *
      * @param columnIndex the zero-based index of the target column.
      * @return the value of that column as a double.
@@ -573,7 +586,8 @@
      * that are required to fetch data for the cursor.
      *
      * <p>These values may only change when requery is called.
-     * @return cursor-defined values, or Bundle.EMTPY if there are no values. Never null.
+     * @return cursor-defined values, or {@link android.os.Bundle#EMPTY Bundle.EMPTY} if there
+     *         are no values. Never <code>null</code>.
      */
     Bundle getExtras();
 
@@ -583,8 +597,10 @@
      *
      * <p>One use of this is to tell a cursor that it should retry its network request after it
      * reported an error.
-     * @param extras extra values, or Bundle.EMTPY. Never null.
-     * @return extra values, or Bundle.EMTPY. Never null.
+     * @param extras extra values, or {@link android.os.Bundle#EMPTY Bundle.EMPTY}.
+     *         Never <code>null</code>.
+     * @return extra values, or {@link android.os.Bundle#EMPTY Bundle.EMPTY}.
+     *         Never <code>null</code>.
      */
     Bundle respond(Bundle extras);
 }
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index c756825..76b91f5 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -245,6 +245,15 @@
         }
     }
 
+    /**
+     * Returns the value at (<code>row</code>, <code>col</code>) as a <code>byte</code> array.
+     *
+     * <p>If the value is null, then <code>null</code> is returned. If the
+     * type of column <code>col</code> is a string type, then the result
+     * is the array of bytes that make up the internal representation of the
+     * string value. If the type of column <code>col</code> is integral or floating-point,
+     * then an {@link SQLiteException} is thrown.
+     */
     private native byte[] getBlob_native(int row, int col);
 
     /**
@@ -332,6 +341,19 @@
         }
     }
     
+    /**
+     * Returns the value at (<code>row</code>, <code>col</code>) as a <code>String</code>.
+     *
+     * <p>If the value is null, then <code>null</code> is returned. If the
+     * type of column <code>col</code> is integral, then the result is the string
+     * that is obtained by formatting the integer value with the <code>printf</code>
+     * family of functions using format specifier <code>%lld</code>. If the
+     * type of column <code>col</code> is floating-point, then the result is the string
+     * that is obtained by formatting the floating-point value with the
+     * <code>printf</code> family of functions using format specifier <code>%g</code>.
+     * If the type of column <code>col</code> is a blob type, then an
+     * {@link SQLiteException} is thrown.
+     */
     private native String getString_native(int row, int col);
 
     /**
@@ -383,6 +405,17 @@
         }
     }
     
+    /**
+     * Returns the value at (<code>row</code>, <code>col</code>) as a <code>long</code>.
+     *
+     * <p>If the value is null, then <code>0L</code> is returned. If the
+     * type of column <code>col</code> is a string type, then the result
+     * is the <code>long</code> that is obtained by parsing the string value with
+     * <code>strtoll</code>. If the type of column <code>col</code> is
+     * floating-point, then the result is the floating-point value casted to a <code>long</code>.
+     * If the type of column <code>col</code> is a blob type, then an
+     * {@link SQLiteException} is thrown.
+     */
     private native long getLong_native(int row, int col);
 
     /**
@@ -402,6 +435,17 @@
         }
     }
     
+    /**
+     * Returns the value at (<code>row</code>, <code>col</code>) as a <code>double</code>.
+     *
+     * <p>If the value is null, then <code>0.0</code> is returned. If the
+     * type of column <code>col</code> is a string type, then the result
+     * is the <code>double</code> that is obtained by parsing the string value with
+     * <code>strtod</code>. If the type of column <code>col</code> is
+     * integral, then the result is the integer value casted to a <code>double</code>.
+     * If the type of column <code>col</code> is a blob type, then an
+     * {@link SQLiteException} is thrown.
+     */
     private native double getDouble_native(int row, int col);
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index c7e58fa..2fd28d7 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -131,11 +131,11 @@
             // the cursor's state doesn't change
             while (true) {
                 mLock.lock();
-                if (mCursorState != mThreadState) {
-                    mLock.unlock();
-                    break;
-                }
                 try {
+                    if (mCursorState != mThreadState) {
+                        break;
+                    }
+
                     int count = mQuery.fillWindow(cw, mMaxRead, mCount);
                     // return -1 means not finished
                     if (count != 0) {
@@ -217,9 +217,8 @@
         mColumnNameMap = null;
         mQuery = query;
 
+        db.lock();
         try {
-            db.lock();
-
             // Setup the list of columns
             int columnCount = mQuery.columnCountLocked();
             mColumns = new String[columnCount];
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 610bf70..b6aca2b 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -321,7 +321,7 @@
         }
 
         String sql = buildQuery(
-                projectionIn, selection, selectionArgs, groupBy, having,
+                projectionIn, selection, groupBy, having,
                 sortOrder, limit);
 
         if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -345,10 +345,6 @@
      *   formatted as an SQL WHERE clause (excluding the WHERE
      *   itself).  Passing null will return all rows for the given
      *   URL.
-     * @param selectionArgs You may include ?s in selection, which
-     *   will be replaced by the values from selectionArgs, in order
-     *   that they appear in the selection.  The values will be bound
-     *   as Strings.
      * @param groupBy A filter declaring how to group rows, formatted
      *   as an SQL GROUP BY clause (excluding the GROUP BY itself).
      *   Passing null will cause the rows to not be grouped.
@@ -365,8 +361,8 @@
      * @return the resulting SQL SELECT statement
      */
     public String buildQuery(
-            String[] projectionIn, String selection, String[] selectionArgs,
-            String groupBy, String having, String sortOrder, String limit) {
+            String[] projectionIn, String selection, String groupBy,
+            String having, String sortOrder, String limit) {
         String[] projection = computeProjection(projectionIn);
 
         StringBuilder where = new StringBuilder();
@@ -394,6 +390,19 @@
     }
 
     /**
+     * @deprecated This method's signature is misleading since no SQL parameter
+     * substitution is carried out.  The selection arguments parameter does not get
+     * used at all.  To avoid confusion, call
+     * {@link #buildQuery(String[], String, String, String, String, String)} instead.
+     */
+    @Deprecated
+    public String buildQuery(
+            String[] projectionIn, String selection, String[] selectionArgs,
+            String groupBy, String having, String sortOrder, String limit) {
+        return buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit);
+    }
+
+    /**
      * Construct a SELECT statement suitable for use in a group of
      * SELECT statements that will be joined through UNION operators
      * in buildUnionQuery.
@@ -422,10 +431,6 @@
      *   formatted as an SQL WHERE clause (excluding the WHERE
      *   itself).  Passing null will return all rows for the given
      *   URL.
-     * @param selectionArgs You may include ?s in selection, which
-     *   will be replaced by the values from selectionArgs, in order
-     *   that they appear in the selection.  The values will be bound
-     *   as Strings.
      * @param groupBy A filter declaring how to group rows, formatted
      *   as an SQL GROUP BY clause (excluding the GROUP BY itself).
      *   Passing null will cause the rows to not be grouped.
@@ -443,7 +448,6 @@
             int computedColumnsOffset,
             String typeDiscriminatorValue,
             String selection,
-            String[] selectionArgs,
             String groupBy,
             String having) {
         int unionColumnsCount = unionColumns.length;
@@ -463,12 +467,36 @@
             }
         }
         return buildQuery(
-                projectionIn, selection, selectionArgs, groupBy, having,
+                projectionIn, selection, groupBy, having,
                 null /* sortOrder */,
                 null /* limit */);
     }
 
     /**
+     * @deprecated This method's signature is misleading since no SQL parameter
+     * substitution is carried out.  The selection arguments parameter does not get
+     * used at all.  To avoid confusion, call
+     * {@link #buildUnionSubQuery}
+     * instead.
+     */
+    @Deprecated
+    public String buildUnionSubQuery(
+            String typeDiscriminatorColumn,
+            String[] unionColumns,
+            Set<String> columnsPresentInTable,
+            int computedColumnsOffset,
+            String typeDiscriminatorValue,
+            String selection,
+            String[] selectionArgs,
+            String groupBy,
+            String having) {
+        return buildUnionSubQuery(
+                typeDiscriminatorColumn, unionColumns, columnsPresentInTable,
+                computedColumnsOffset, typeDiscriminatorValue, selection,
+                groupBy, having);
+    }
+
+    /**
      * Given a set of subqueries, all of which are SELECT statements,
      * construct a query that returns the union of what those
      * subqueries return.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index c9df567..1db8f68 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -292,6 +292,10 @@
         } catch (RuntimeException e) {
             reply.writeException(e);
             res = true;
+        } catch (OutOfMemoryError e) {
+            RuntimeException re = new RuntimeException("Out of memory", e);
+            reply.writeException(re);
+            res = true;
         }
         reply.recycle();
         data.recycle();
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 7889a92..4a0612c 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -150,7 +150,12 @@
             try {
                 is = getInputStream();
                 byte[] buf = new byte[maxBytes];
-                return new String(buf, 0, Math.max(0, is.read(buf)));
+                int readBytes = 0;
+                int n = 0;
+                while (n >= 0 && (readBytes += n) < maxBytes) {
+                    n = is.read(buf, readBytes, maxBytes - readBytes);
+                }
+                return new String(buf, 0, readBytes);
             } catch (IOException e) {
                 return null;
             } finally {
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index bbad2b6..45c8174 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -322,7 +322,7 @@
     private void requestInputMethod(Dialog dialog) {
         Window window = dialog.getWindow();
         window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE |
-                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
     }
 
     /**
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 7fd993a..021b53c 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -18,6 +18,7 @@
 
 import android.net.http.EventHandler;
 import android.net.http.RequestHandle;
+import android.os.Build;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
 
@@ -35,6 +36,7 @@
     private int mCacheMode;
     private String mReferrer;
     private String mContentType;
+    private final String mUaprofHeader;
 
     private static final int URI_PROTOCOL = 0x100;
 
@@ -57,6 +59,8 @@
         mMethod = method;
         mCacheMode = WebSettings.LOAD_NORMAL;
         mSettings = settings;
+        mUaprofHeader = mListener.getContext().getResources().getString(
+                com.android.internal.R.string.config_useragentprofile_url, Build.MODEL);
     }
 
     public void setReferrer(String ref) {
@@ -356,6 +360,11 @@
         }
         
         mHeaders.put("User-Agent", mSettings.getUserAgentString());
+
+        // Set the x-wap-profile header
+        if (mUaprofHeader != null && mUaprofHeader.length() > 0) {
+            mHeaders.put("x-wap-profile", mUaprofHeader);
+        }
     }
 
     /**
diff --git a/core/java/android/widget/AbsoluteLayout.java b/core/java/android/widget/AbsoluteLayout.java
index b829655..970cbe35 100644
--- a/core/java/android/widget/AbsoluteLayout.java
+++ b/core/java/android/widget/AbsoluteLayout.java
@@ -187,7 +187,7 @@
          * </ul>
          *
          * @param c the application environment
-         * @param attrs the set of attributes fom which to extract the layout
+         * @param attrs the set of attributes from which to extract the layout
          *              parameters values
          */
         public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 4e1b585..830fcd1 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -106,7 +106,6 @@
     }
 
     private void initTabWidget() {
-        setOrientation(LinearLayout.HORIZONTAL);
         mGroupFlags |= FLAG_USE_CHILD_DRAWING_ORDER;
 
         final Context context = mContext;
diff --git a/core/res/res/layout/tab_content.xml b/core/res/res/layout/tab_content.xml
index 0ee87ce..79147fb 100644
--- a/core/res/res/layout/tab_content.xml
+++ b/core/res/res/layout/tab_content.xml
@@ -22,8 +22,9 @@
 	android:layout_width="match_parent" android:layout_height="match_parent">
 	<LinearLayout android:orientation="vertical"
     	android:layout_width="match_parent" android:layout_height="match_parent">
-        <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent"
-        	android:layout_height="wrap_content" android:layout_weight="0" />
+    <TabWidget android:id="@android:id/tabs"
+        android:orientation="horizontal" android:layout_width="match_parent"
+        android:layout_height="wrap_content" android:layout_weight="0" />
         <FrameLayout android:id="@android:id/tabcontent"
         	android:layout_width="match_parent" android:layout_height="0dip"
             android:layout_weight="1"/>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 59e4a55..ebfab91 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -332,4 +332,11 @@
     <!-- 2 means give warning -->
     <integer name="config_datause_notification_type">2</integer>
 
+    <!-- The URL that should be sent in an x-wap-profile header with an HTTP request,
+         as defined in the Open Mobile Alliance User Agent Profile specification
+         OMA-TS-UAProf-V2_0-20060206-A Section 8.1.1.1. If the URL contains a '%s'
+         format string then that substring will be replaced with the value of
+         Build.MODEL. The format string shall not be escaped. -->
+    <string name="config_useragentprofile_url"></string>
+
 </resources>
diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp
index 17cdf544..10c64ee 100644
--- a/drm/common/DrmEngineBase.cpp
+++ b/drm/common/DrmEngineBase.cpp
@@ -120,6 +120,11 @@
     return onOpenDecryptSession(uniqueId, decryptHandle, fd, offset, length);
 }
 
+status_t DrmEngineBase::openDecryptSession(
+    int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
+    return onOpenDecryptSession(uniqueId, decryptHandle, uri);
+}
+
 status_t DrmEngineBase::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
     return onCloseDecryptSession(uniqueId, decryptHandle);
 }
diff --git a/drm/common/DrmInfoStatus.cpp b/drm/common/DrmInfoStatus.cpp
index f3a1516..8ec7311 100644
--- a/drm/common/DrmInfoStatus.cpp
+++ b/drm/common/DrmInfoStatus.cpp
@@ -19,8 +19,9 @@
 using namespace android;
 
 DrmInfoStatus::DrmInfoStatus(
-    int _statusCode, const DrmBuffer* _drmBuffer, const String8& _mimeType) :
+    int _statusCode, int _infoType, const DrmBuffer* _drmBuffer, const String8& _mimeType) :
     statusCode(_statusCode),
+    infoType(_infoType),
     drmBuffer(_drmBuffer),
     mimeType(_mimeType) {
 
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index c28527c..b8ae852 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -53,27 +53,18 @@
     remote()->transact(REMOVE_UNIQUEID, data, &reply);
 }
 
-status_t BpDrmManagerService::loadPlugIns(int uniqueId) {
-    LOGV("load plugins");
+void BpDrmManagerService::addClient(int uniqueId) {
     Parcel data, reply;
-
     data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
     data.writeInt32(uniqueId);
-
-    remote()->transact(LOAD_PLUGINS, data, &reply);
-    return reply.readInt32();
+    remote()->transact(ADD_CLIENT, data, &reply);
 }
 
-status_t BpDrmManagerService::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
-    LOGV("load plugins from path");
+void BpDrmManagerService::removeClient(int uniqueId) {
     Parcel data, reply;
-
     data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
     data.writeInt32(uniqueId);
-    data.writeString8(plugInDirPath);
-
-    remote()->transact(LOAD_PLUGINS_FROM_PATH, data, &reply);
-    return reply.readInt32();
+    remote()->transact(REMOVE_CLIENT, data, &reply);
 }
 
 status_t BpDrmManagerService::setDrmServiceListener(
@@ -88,17 +79,6 @@
     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;
@@ -191,6 +171,7 @@
     if (0 != reply.dataAvail()) {
         //Filling DRM Info Status
         const int statusCode = reply.readInt32();
+        const int infoType = reply.readInt32();
         const String8 mimeType = reply.readString8();
 
         DrmBuffer* drmBuffer = NULL;
@@ -203,7 +184,7 @@
             }
             drmBuffer = new DrmBuffer(data, bufferSize);
         }
-        drmInfoStatus = new DrmInfoStatus(statusCode, drmBuffer, mimeType);
+        drmInfoStatus = new DrmInfoStatus(statusCode, infoType, drmBuffer, mimeType);
     }
     return drmInfoStatus;
 }
@@ -538,8 +519,7 @@
     LOGV("Entering BpDrmManagerService::openDecryptSession");
     Parcel data, reply;
 
-    const String16 interfaceDescriptor = IDrmManagerService::getInterfaceDescriptor();
-    data.writeInterfaceToken(interfaceDescriptor);
+    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
     data.writeInt32(uniqueId);
     data.writeFileDescriptor(fd);
     data.writeInt32(offset);
@@ -565,6 +545,34 @@
     return handle;
 }
 
+DecryptHandle* BpDrmManagerService::openDecryptSession(int uniqueId, const char* uri) {
+    LOGV("Entering BpDrmManagerService::openDecryptSession");
+    Parcel data, reply;
+
+    data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+    data.writeInt32(uniqueId);
+    data.writeString8(String8(uri));
+
+    remote()->transact(OPEN_DECRYPT_SESSION_FROM_URI, data, &reply);
+
+    DecryptHandle* handle = NULL;
+    if (0 != reply.dataAvail()) {
+        handle = new DecryptHandle();
+        handle->decryptId = reply.readInt32();
+        handle->mimeType = reply.readString8();
+        handle->decryptApiType = reply.readInt32();
+        handle->status = reply.readInt32();
+        handle->decryptInfo = NULL;
+        if (0 != reply.dataAvail()) {
+            handle->decryptInfo = new DecryptInfo();
+            handle->decryptInfo->decryptBufferLength = reply.readInt32();
+        }
+    } else {
+        LOGE("no decryptHandle is generated in service side");
+    }
+    return handle;
+}
+
 status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
     LOGV("closeDecryptSession");
     Parcel data, reply;
@@ -746,25 +754,19 @@
         return DRM_NO_ERROR;
     }
 
-    case LOAD_PLUGINS:
+    case ADD_CLIENT:
     {
-        LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS");
+        LOGV("BnDrmManagerService::onTransact :ADD_CLIENT");
         CHECK_INTERFACE(IDrmManagerService, data, reply);
-
-        status_t status = loadPlugIns(data.readInt32());
-
-        reply->writeInt32(status);
+        addClient(data.readInt32());
         return DRM_NO_ERROR;
     }
 
-    case LOAD_PLUGINS_FROM_PATH:
+    case REMOVE_CLIENT:
     {
-        LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS_FROM_PATH");
+        LOGV("BnDrmManagerService::onTransact :REMOVE_CLIENT");
         CHECK_INTERFACE(IDrmManagerService, data, reply);
-
-        status_t status = loadPlugIns(data.readInt32(), data.readString8());
-
-        reply->writeInt32(status);
+        removeClient(data.readInt32());
         return DRM_NO_ERROR;
     }
 
@@ -783,18 +785,6 @@
         return DRM_NO_ERROR;
     }
 
-    case UNLOAD_PLUGINS:
-    {
-        LOGV("BnDrmManagerService::onTransact :UNLOAD_PLUGINS");
-        CHECK_INTERFACE(IDrmManagerService, data, reply);
-
-        const int uniqueId = data.readInt32();
-        status_t status = unloadPlugIns(uniqueId);
-
-        reply->writeInt32(status);
-        return DRM_NO_ERROR;
-    }
-
     case INSTALL_DRM_ENGINE:
     {
         LOGV("BnDrmManagerService::onTransact :INSTALL_DRM_ENGINE");
@@ -881,6 +871,7 @@
         if (NULL != drmInfoStatus) {
             //Filling DRM Info Status contents
             reply->writeInt32(drmInfoStatus->statusCode);
+            reply->writeInt32(drmInfoStatus->infoType);
             reply->writeString8(drmInfoStatus->mimeType);
 
             if (NULL != drmInfoStatus->drmBuffer) {
@@ -1239,6 +1230,32 @@
         return DRM_NO_ERROR;
     }
 
+    case OPEN_DECRYPT_SESSION_FROM_URI:
+    {
+        LOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION_FROM_URI");
+        CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+        const int uniqueId = data.readInt32();
+        const String8 uri = data.readString8();
+
+        DecryptHandle* handle = openDecryptSession(uniqueId, uri.string());
+
+        if (NULL != handle) {
+            reply->writeInt32(handle->decryptId);
+            reply->writeString8(handle->mimeType);
+            reply->writeInt32(handle->decryptApiType);
+            reply->writeInt32(handle->status);
+            if (NULL != handle->decryptInfo) {
+                reply->writeInt32(handle->decryptInfo->decryptBufferLength);
+                delete handle->decryptInfo; handle->decryptInfo = NULL;
+            }
+        } else {
+            LOGE("NULL decryptHandle is returned");
+        }
+        delete handle; handle = NULL;
+        return DRM_NO_ERROR;
+    }
+
     case CLOSE_DECRYPT_SESSION:
     {
         LOGV("BnDrmManagerService::onTransact :CLOSE_DECRYPT_SESSION");
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 52527dc..b7a035f 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -85,22 +85,31 @@
     }
 }
 
-status_t DrmManager::loadPlugIns(int uniqueId) {
+status_t DrmManager::loadPlugIns() {
     String8 pluginDirPath("/system/lib/drm/plugins/native");
-    return loadPlugIns(uniqueId, pluginDirPath);
+    return loadPlugIns(pluginDirPath);
 }
 
-status_t DrmManager::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
+status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
     if (mSupportInfoToPlugInIdMap.isEmpty()) {
         mPlugInManager.loadPlugIns(plugInDirPath);
-
-        initializePlugIns(uniqueId);
-
-        populate(uniqueId);
-    } else {
-        initializePlugIns(uniqueId);
+        Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+        for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+            String8 plugInPath = plugInPathList[i];
+            DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
+            if (NULL != info) {
+                mSupportInfoToPlugInIdMap.add(*info, plugInPath);
+            }
+        }
     }
+    return DRM_NO_ERROR;
+}
 
+status_t DrmManager::unloadPlugIns() {
+    mConvertSessionMap.clear();
+    mDecryptSessionMap.clear();
+    mPlugInManager.unloadPlugIns();
+    mSupportInfoToPlugInIdMap.clear();
     return DRM_NO_ERROR;
 }
 
@@ -111,21 +120,23 @@
     return DRM_NO_ERROR;
 }
 
-status_t DrmManager::unloadPlugIns(int uniqueId) {
-    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+void DrmManager::addClient(int uniqueId) {
+    if (!mSupportInfoToPlugInIdMap.isEmpty()) {
+        Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+            rDrmEngine.initialize(uniqueId);
+            rDrmEngine.setOnInfoListener(uniqueId, this);
+        }
+    }
+}
 
+void DrmManager::removeClient(int uniqueId) {
+    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
     for (unsigned int index = 0; index < plugInIdList.size(); index++) {
         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
         rDrmEngine.terminate(uniqueId);
     }
-
-    if (0 >= mUniqueIdVector.size()) {
-        mConvertSessionMap.clear();
-        mDecryptSessionMap.clear();
-        mSupportInfoToPlugInIdMap.clear();
-        mPlugInManager.unloadPlugIns();
-    }
-    return DRM_NO_ERROR;
 }
 
 DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
@@ -144,7 +155,7 @@
     rDrmEngine.initialize(uniqueId);
     rDrmEngine.setOnInfoListener(uniqueId, this);
 
-    DrmSupportInfo* info = rDrmEngine.getSupportInfo(uniqueId);
+    DrmSupportInfo* info = rDrmEngine.getSupportInfo(0);
     mSupportInfoToPlugInIdMap.add(*info, absolutePath);
 
     return DRM_NO_ERROR;
@@ -154,7 +165,7 @@
     const String8 plugInId = getSupportedPlugInId(mimeType);
     bool result = (EMPTY_STRING != plugInId) ? true : false;
 
-    if (NULL != path) {
+    if (0 < path.length()) {
         if (result) {
             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
             result = rDrmEngine.canHandle(uniqueId, path);
@@ -340,7 +351,7 @@
         for (int i = 0; i < size; ++i) {
             String8 plugInPath = plugInPathList[i];
             DrmSupportInfo* drmSupportInfo
-                = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(uniqueId);
+                = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
             if (NULL != drmSupportInfo) {
                 drmSupportInfoList.add(*drmSupportInfo);
                 delete drmSupportInfo; drmSupportInfo = NULL;
@@ -360,12 +371,12 @@
 }
 
 DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, int offset, int length) {
+    Mutex::Autolock _l(mDecryptLock);
     status_t result = DRM_ERROR_CANNOT_HANDLE;
     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
 
     DecryptHandle* handle = new DecryptHandle();
     if (NULL != handle) {
-        Mutex::Autolock _l(mDecryptLock);
         handle->decryptId = mDecryptSessionId + 1;
 
         for (unsigned int index = 0; index < plugInIdList.size(); index++) {
@@ -380,16 +391,43 @@
             }
         }
     }
-
     if (DRM_NO_ERROR != result) {
         delete handle; handle = NULL;
         LOGE("DrmManager::openDecryptSession: no capable plug-in found");
     }
+    return handle;
+}
 
+DecryptHandle* DrmManager::openDecryptSession(int uniqueId, const char* uri) {
+    Mutex::Autolock _l(mDecryptLock);
+    status_t result = DRM_ERROR_CANNOT_HANDLE;
+    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+    DecryptHandle* handle = new DecryptHandle();
+    if (NULL != handle) {
+        handle->decryptId = mDecryptSessionId + 1;
+
+        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+            String8 plugInId = plugInIdList.itemAt(index);
+            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+            result = rDrmEngine.openDecryptSession(uniqueId, handle, uri);
+
+            if (DRM_NO_ERROR == result) {
+                ++mDecryptSessionId;
+                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+                break;
+            }
+        }
+    }
+    if (DRM_NO_ERROR != result) {
+        delete handle; handle = NULL;
+        LOGE("DrmManager::openDecryptSession: no capable plug-in found");
+    }
     return handle;
 }
 
 status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+    Mutex::Autolock _l(mDecryptLock);
     status_t result = DRM_ERROR_UNKNOWN;
     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
@@ -443,28 +481,6 @@
     return result;
 }
 
-void DrmManager::initializePlugIns(int uniqueId) {
-    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
-
-    for (unsigned int index = 0; index < plugInIdList.size(); index++) {
-        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
-        rDrmEngine.initialize(uniqueId);
-        rDrmEngine.setOnInfoListener(uniqueId, this);
-    }
-}
-
-void DrmManager::populate(int uniqueId) {
-    Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
-
-    for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
-        String8 plugInPath = plugInPathList[i];
-        DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(uniqueId);
-        if (NULL != info) {
-            mSupportInfoToPlugInIdMap.add(*info, plugInPath);
-        }
-    }
-}
-
 String8 DrmManager::getSupportedPlugInId(
             int uniqueId, const String8& path, const String8& mimeType) {
     String8 plugInId("");
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 843dddb..8cf510d 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -27,36 +27,21 @@
 
 using namespace android;
 
-#define SUCCESS 0
-#define DRM_DIRECTORY_PERMISSION 0700
-#define DRM_PLUGINS_ROOT "/data/drm/plugins"
-#define DRM_PLUGINS_NATIVE "/data/drm/plugins/native"
-#define DRM_PLUGINS_NATIVE_DATABASES "/data/drm/plugins/native/databases"
-
 void DrmManagerService::instantiate() {
     LOGV("instantiate");
-
-    int res = mkdir(DRM_PLUGINS_ROOT, DRM_DIRECTORY_PERMISSION);
-    if (SUCCESS == res || EEXIST == errno) {
-        res = mkdir(DRM_PLUGINS_NATIVE, DRM_DIRECTORY_PERMISSION);
-        if (SUCCESS == res || EEXIST == errno) {
-            res = mkdir(DRM_PLUGINS_NATIVE_DATABASES, DRM_DIRECTORY_PERMISSION);
-            if (SUCCESS == res || EEXIST == errno) {
-                defaultServiceManager()
-                    ->addService(String16("drm.drmManager"), new DrmManagerService());
-            }
-        }
-    }
+    defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
 }
 
-DrmManagerService::DrmManagerService() {
+DrmManagerService::DrmManagerService() :
+        mDrmManager(NULL) {
     LOGV("created");
-    mDrmManager = NULL;
     mDrmManager = new DrmManager();
+    mDrmManager->loadPlugIns();
 }
 
 DrmManagerService::~DrmManagerService() {
     LOGV("Destroyed");
+    mDrmManager->unloadPlugIns();
     delete mDrmManager; mDrmManager = NULL;
 }
 
@@ -68,14 +53,12 @@
     mDrmManager->removeUniqueId(uniqueId);
 }
 
-status_t DrmManagerService::loadPlugIns(int uniqueId) {
-    LOGV("Entering load plugins");
-    return mDrmManager->loadPlugIns(uniqueId);
+void DrmManagerService::addClient(int uniqueId) {
+    mDrmManager->addClient(uniqueId);
 }
 
-status_t DrmManagerService::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
-    LOGV("Entering load plugins from path");
-    return mDrmManager->loadPlugIns(uniqueId, plugInDirPath);
+void DrmManagerService::removeClient(int uniqueId) {
+    mDrmManager->removeClient(uniqueId);
 }
 
 status_t DrmManagerService::setDrmServiceListener(
@@ -85,11 +68,6 @@
     return DRM_NO_ERROR;
 }
 
-status_t DrmManagerService::unloadPlugIns(int uniqueId) {
-    LOGV("Entering unload plugins");
-    return mDrmManager->unloadPlugIns(uniqueId);
-}
-
 status_t DrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
     LOGV("Entering installDrmEngine");
     return mDrmManager->installDrmEngine(uniqueId, drmEngineFile);
@@ -197,6 +175,12 @@
     return mDrmManager->openDecryptSession(uniqueId, fd, offset, length);
 }
 
+DecryptHandle* DrmManagerService::openDecryptSession(
+            int uniqueId, const char* uri) {
+    LOGV("Entering DrmManagerService::openDecryptSession with uri");
+    return mDrmManager->openDecryptSession(uniqueId, uri);
+}
+
 status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
     LOGV("Entering closeDecryptSession");
     return mDrmManager->closeDecryptSession(uniqueId, decryptHandle);
diff --git a/drm/java/android/drm/DrmErrorEvent.java b/drm/java/android/drm/DrmErrorEvent.java
index 8e71634..9294884 100644
--- a/drm/java/android/drm/DrmErrorEvent.java
+++ b/drm/java/android/drm/DrmErrorEvent.java
@@ -45,35 +45,19 @@
      */
     public static final int TYPE_NO_INTERNET_CONNECTION = 2005;
     /**
-     * TYPE_REGISTRATION_FAILED, when failed to register with the service.
+     * TYPE_PROCESS_DRM_INFO_FAILED, when failed to process DrmInfo.
      */
-    public static final int TYPE_REGISTRATION_FAILED = 2006;
-    /**
-     * TYPE_UNREGISTRATION_FAILED, when failed to unregister with the service.
-     */
-    public static final int TYPE_UNREGISTRATION_FAILED = 2007;
-    /**
-     * TYPE_RIGHTS_ACQUISITION_FAILED, when failed to acquire the rights information required.
-     */
-    public static final int TYPE_RIGHTS_ACQUISITION_FAILED = 2008;
-    /**
-     * TYPE_INITIALIZE_FAILED, when failed to load and initialize the available plugins.
-     */
-    public static final int TYPE_INITIALIZE_FAILED = 2009;
-    /**
-     * TYPE_FINALIZE_FAILED, when failed to unload and finalize the loaded plugins.
-     */
-    public static final int TYPE_FINALIZE_FAILED = 2010;
+    public static final int TYPE_PROCESS_DRM_INFO_FAILED = 2006;
     /**
      * TYPE_REMOVE_ALL_RIGHTS_FAILED, when failed to remove all the rights objects
      * associated with all DRM schemes.
      */
-    public static final int TYPE_REMOVE_ALL_RIGHTS_FAILED = 2011;
+    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 = 2012;
+    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 d6e0c3a..583337f 100644
--- a/drm/java/android/drm/DrmEvent.java
+++ b/drm/java/android/drm/DrmEvent.java
@@ -23,35 +23,19 @@
  */
 public class DrmEvent {
     /**
-     * Constant field signifies that unload and finalize the loaded plugins successfully
-     */
-    public static final int TYPE_FINALIZED = 1001;
-    /**
-     * Constant field signifies that register with the service successfully
-     */
-    public static final int TYPE_REGISTERED = 1002;
-    /**
-     * Constant field signifies that load and initialized the available plugins successfully
-     */
-    public static final int TYPE_INITIALIZED = 1003;
-    /**
-     * Constant field signifies that unregister with the service successfully
-     */
-    public static final int TYPE_UNREGISTERED = 1004;
-    /**
-     * Constant field signifies that rights information is acquired successfully
-     */
-    public static final int TYPE_RIGHTS_ACQUIRED = 1005;
-    /**
      * Constant field signifies that all the rights information associated with
      * all DRM schemes are removed successfully
      */
-    public static final int TYPE_ALL_RIGHTS_REMOVED = 1006;
+    public static final int TYPE_ALL_RIGHTS_REMOVED = 1001;
+    /**
+     * 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 = 1007;
+    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";
diff --git a/drm/java/android/drm/DrmInfoStatus.java b/drm/java/android/drm/DrmInfoStatus.java
index 7e9ca3e..b37ea51 100644
--- a/drm/java/android/drm/DrmInfoStatus.java
+++ b/drm/java/android/drm/DrmInfoStatus.java
@@ -31,6 +31,7 @@
     public static final int STATUS_ERROR = 2;
 
     public final int statusCode;
+    public final int infoType;
     public final String mimeType;
     public final ProcessedData data;
 
@@ -38,11 +39,13 @@
      * constructor to create DrmInfoStatus object with given parameters
      *
      * @param _statusCode Status of the communication
+     * @param _infoType Type of the DRM information processed
      * @param _data The processed data
      * @param _mimeType MIME type
      */
-    public DrmInfoStatus(int _statusCode, ProcessedData _data, String _mimeType) {
+    public DrmInfoStatus(int _statusCode, int _infoType, ProcessedData _data, String _mimeType) {
         statusCode = _statusCode;
+        infoType = _infoType;
         data = _data;
         mimeType = _mimeType;
     }
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 147c530..5044d36 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -16,9 +16,11 @@
 
 package android.drm;
 
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -99,14 +101,9 @@
         public void onError(DrmManagerClient client, DrmErrorEvent event);
     }
 
-    private static final int STATE_UNINITIALIZED = 0;
-    private static final int STATE_INITIALIZED = 1;
-
-    private static final int ACTION_INITIALIZE = 1000;
-    private static final int ACTION_FINALIZE = 1001;
-    private static final int ACTION_REMOVE_ALL_RIGHTS = 1002;
-    private static final int ACTION_ACQUIRE_DRM_INFO = 1003;
-    private static final int ACTION_PROCESS_DRM_INFO = 1004;
+    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 int mUniqueId;
     private int mNativeContext;
@@ -116,7 +113,6 @@
     private OnInfoListener mOnInfoListener;
     private OnEventListener mOnEventListener;
     private OnErrorListener mOnErrorListener;
-    private int mCurrentState = STATE_UNINITIALIZED;
 
     private class EventHandler extends Handler {
 
@@ -130,16 +126,6 @@
             HashMap<String, Object> attributes = new HashMap<String, Object>();
 
             switch(msg.what) {
-            case ACTION_INITIALIZE: {
-                if (ERROR_NONE == _loadPlugIns(mUniqueId, msg.obj)) {
-                    mCurrentState = STATE_INITIALIZED;
-                    event = new DrmEvent(mUniqueId, DrmEvent.TYPE_INITIALIZED, null);
-                } else {
-                    error = new DrmErrorEvent(mUniqueId,
-                            DrmErrorEvent.TYPE_INITIALIZE_FAILED, null);
-                }
-                break;
-            }
             case ACTION_ACQUIRE_DRM_INFO: {
                 final DrmInfoRequest request = (DrmInfoRequest) msg.obj;
                 DrmInfo drmInfo = _acquireDrmInfo(mUniqueId, request);
@@ -157,10 +143,10 @@
                 DrmInfoStatus status = _processDrmInfo(mUniqueId, drmInfo);
                 if (null != status && DrmInfoStatus.STATUS_OK == status.statusCode) {
                     attributes.put(DrmEvent.DRM_INFO_STATUS_OBJECT, status);
-                    event = new DrmEvent(mUniqueId, getEventType(drmInfo.getInfoType()), null);
+                    event = new DrmEvent(mUniqueId, getEventType(status.infoType), null);
                 } else {
-                    error = new DrmErrorEvent(mUniqueId,
-                            getErrorType(drmInfo.getInfoType()), null);
+                    int infoType = (null != status) ? status.infoType : drmInfo.getInfoType();
+                    error = new DrmErrorEvent(mUniqueId, getErrorType(infoType), null);
                 }
                 break;
             }
@@ -173,16 +159,6 @@
                 }
                 break;
             }
-            case ACTION_FINALIZE: {
-                if (ERROR_NONE == _unloadPlugIns(mUniqueId)) {
-                    mCurrentState = STATE_UNINITIALIZED;
-                    event = new DrmEvent(mUniqueId, DrmEvent.TYPE_FINALIZED, null);
-                } else {
-                    error = new DrmErrorEvent(mUniqueId,
-                            DrmErrorEvent.TYPE_FINALIZE_FAILED, null);
-                }
-                break;
-            }
             default:
                 Log.e(TAG, "Unknown message type " + msg.what);
                 return;
@@ -283,6 +259,12 @@
 
         // save the unique id
         mUniqueId = hashCode();
+
+        _initialize(mUniqueId, new WeakReference<DrmManagerClient>(this));
+    }
+
+    protected void finalize() {
+        _finalize(mUniqueId);
     }
 
     /**
@@ -322,58 +304,11 @@
     }
 
     /**
-     * Initializes DrmFramework, which loads all available plug-ins
-     * in the default plug-in directory path
-     *
-     * @return
-     *     ERROR_NONE for success
-     *     ERROR_UNKNOWN for failure
-     */
-    public int loadPlugIns() {
-        int result = ERROR_UNKNOWN;
-        if (STATE_UNINITIALIZED == getState()) {
-            if (null != mEventHandler) {
-                Message msg = mEventHandler.obtainMessage(
-                        ACTION_INITIALIZE, new WeakReference<DrmManagerClient>(this));
-                result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
-            }
-        } else {
-            result = ERROR_NONE;
-        }
-        return result;
-    }
-
-    /**
-     * Finalize DrmFramework, which release resources associated with each plug-in
-     * and unload all plug-ins.
-     *
-     * @return
-     *     ERROR_NONE for success
-     *     ERROR_UNKNOWN for failure
-     */
-    public int unloadPlugIns() {
-        int result = ERROR_UNKNOWN;
-        if (STATE_INITIALIZED == getState()) {
-            if (null != mEventHandler) {
-                Message msg = mEventHandler.obtainMessage(ACTION_FINALIZE);
-                result = (mEventHandler.sendMessage(msg)) ? ERROR_NONE : result;
-            }
-        } else {
-            result = ERROR_NONE;
-        }
-        return result;
-    }
-
-    /**
      * Retrieves informations about all the plug-ins registered with DrmFramework.
      *
      * @return Array of DrmEngine plug-in strings
      */
     public String[] getAvailableDrmEngines() {
-        if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
-        }
-
         DrmSupportInfo[] supportInfos = _getAllSupportInfo(mUniqueId);
         ArrayList<String> descriptions = new ArrayList<String>();
 
@@ -396,8 +331,6 @@
     public ContentValues getConstraints(String path, int action) {
         if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
             throw new IllegalArgumentException("Given usage or path is invalid/null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _getConstraints(mUniqueId, path, action);
     }
@@ -411,6 +344,9 @@
      *         or null in case of failure
      */
     public ContentValues getConstraints(Uri uri, int action) {
+        if (null == uri || Uri.EMPTY == uri) {
+            throw new IllegalArgumentException("Uri should be non null");
+        }
         return getConstraints(convertUriToPath(uri), action);
     }
 
@@ -432,8 +368,6 @@
             DrmRights drmRights, String rightsPath, String contentPath) throws IOException {
         if (null == drmRights || !drmRights.isValid()) {
             throw new IllegalArgumentException("Given drmRights or contentPath is not valid");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         if (null != rightsPath && !rightsPath.equals("")) {
             DrmUtils.writeToFile(rightsPath, drmRights.getData());
@@ -451,8 +385,6 @@
         if (null == engineFilePath || engineFilePath.equals("")) {
             throw new IllegalArgumentException(
                 "Given engineFilePath: "+ engineFilePath + "is not valid");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         _installDrmEngine(mUniqueId, engineFilePath);
     }
@@ -464,14 +396,11 @@
      * @param mimeType Mimetype of the object to be handled
      * @return
      *        true - if the given mimeType or path can be handled
-     *        false - cannot be handled. false will be return in case
-     *        the state is uninitialized
+     *        false - cannot be handled.
      */
     public boolean canHandle(String path, String mimeType) {
         if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
             throw new IllegalArgumentException("Path or the mimetype should be non null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _canHandle(mUniqueId, path, mimeType);
     }
@@ -483,8 +412,7 @@
      * @param mimeType Mimetype of the object to be handled
      * @return
      *        true - if the given mimeType or path can be handled
-     *        false - cannot be handled. false will be return in case
-     *        the state is uninitialized
+     *        false - cannot be handled.
      */
     public boolean canHandle(Uri uri, String mimeType) {
         if ((null == uri || Uri.EMPTY == uri) && (null == mimeType || mimeType.equals(""))) {
@@ -504,8 +432,6 @@
     public int processDrmInfo(DrmInfo drmInfo) {
         if (null == drmInfo || !drmInfo.isValid()) {
             throw new IllegalArgumentException("Given drmInfo is invalid/null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         int result = ERROR_UNKNOWN;
         if (null != mEventHandler) {
@@ -526,8 +452,6 @@
     public int acquireDrmInfo(DrmInfoRequest drmInfoRequest) {
         if (null == drmInfoRequest || !drmInfoRequest.isValid()) {
             throw new IllegalArgumentException("Given drmInfoRequest is invalid/null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         int result = ERROR_UNKNOWN;
         if (null != mEventHandler) {
@@ -550,8 +474,6 @@
     public int getDrmObjectType(String path, String mimeType) {
         if ((null == path || path.equals("")) && (null == mimeType || mimeType.equals(""))) {
             throw new IllegalArgumentException("Path or the mimetype should be non null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _getDrmObjectType(mUniqueId, path, mimeType);
     }
@@ -589,8 +511,6 @@
     public String getOriginalMimeType(String path) {
         if (null == path || path.equals("")) {
             throw new IllegalArgumentException("Given path should be non null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _getOriginalMimeType(mUniqueId, path);
     }
@@ -644,8 +564,6 @@
     public int checkRightsStatus(String path, int action) {
         if (null == path || path.equals("") || !DrmStore.Action.isValid(action)) {
             throw new IllegalArgumentException("Given path or action is not valid");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _checkRightsStatus(mUniqueId, path, action);
     }
@@ -676,8 +594,6 @@
     public int removeRights(String path) {
         if (null == path || path.equals("")) {
             throw new IllegalArgumentException("Given path should be non null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _removeRights(mUniqueId, path);
     }
@@ -706,9 +622,6 @@
      *     ERROR_UNKNOWN for failure
      */
     public int removeAllRights() {
-        if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
-        }
         int result = ERROR_UNKNOWN;
         if (null != mEventHandler) {
             Message msg = mEventHandler.obtainMessage(ACTION_REMOVE_ALL_RIGHTS);
@@ -729,8 +642,6 @@
     public int openConvertSession(String mimeType) {
         if (null == mimeType || mimeType.equals("")) {
             throw new IllegalArgumentException("Path or the mimeType should be non null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _openConvertSession(mUniqueId, mimeType);
     }
@@ -750,8 +661,6 @@
     public DrmConvertedStatus convertData(int convertId, byte[] inputData) {
         if (null == inputData || 0 >= inputData.length) {
             throw new IllegalArgumentException("Given inputData should be non null");
-        } else if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
         }
         return _convertData(mUniqueId, convertId, inputData);
     }
@@ -769,28 +678,17 @@
      *     the application on which offset these signature data should be appended.
      */
     public DrmConvertedStatus closeConvertSession(int convertId) {
-        if (STATE_UNINITIALIZED == getState()) {
-            throw new IllegalStateException("Not Initialized yet");
-        }
         return _closeConvertSession(mUniqueId, convertId);
     }
 
-    private int getState() {
-        return mCurrentState;
-    }
-
     private int getEventType(int infoType) {
         int eventType = -1;
 
         switch (infoType) {
         case DrmInfoRequest.TYPE_REGISTRATION_INFO:
-            eventType = DrmEvent.TYPE_REGISTERED;
-            break;
         case DrmInfoRequest.TYPE_UNREGISTRATION_INFO:
-            eventType = DrmEvent.TYPE_UNREGISTERED;
-            break;
         case DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO:
-            eventType = DrmEvent.TYPE_RIGHTS_ACQUIRED;
+            eventType = DrmEvent.TYPE_DRM_INFO_PROCESSED;
             break;
         }
         return eventType;
@@ -801,13 +699,9 @@
 
         switch (infoType) {
         case DrmInfoRequest.TYPE_REGISTRATION_INFO:
-            error = DrmErrorEvent.TYPE_REGISTRATION_FAILED;
-            break;
         case DrmInfoRequest.TYPE_UNREGISTRATION_INFO:
-            error = DrmErrorEvent.TYPE_UNREGISTRATION_FAILED;
-            break;
         case DrmInfoRequest.TYPE_RIGHTS_ACQUISITION_INFO:
-            error = DrmErrorEvent.TYPE_RIGHTS_ACQUISITION_FAILED;
+            error = DrmErrorEvent.TYPE_PROCESS_DRM_INFO_FAILED;
             break;
         }
         return error;
@@ -822,25 +716,35 @@
      * <row_index> the index of the content in given table
      */
     private String convertUriToPath(Uri uri) {
+        String path = null;
         String scheme = uri.getScheme();
-        if (null == scheme || scheme.equals("file")) {
-            return uri.getPath();
+        if (null == scheme || scheme.equals("") || scheme.equals(ContentResolver.SCHEME_FILE)) {
+            path = uri.getPath();
+        } else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
+            String[] projection = new String[] {MediaStore.MediaColumns.DATA};
+            Cursor cursor = null;
+            try {
+                cursor = mContext.getContentResolver().query(uri, projection, null, null, null);
+            } catch (SQLiteException e) {
+                throw new IllegalArgumentException("Given Uri is not formatted in a way " +
+                        "so that it can be found in media store.");
+            }
+            if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
+                throw new IllegalArgumentException("Given Uri could not be found in media store");
+            }
+            int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
+            path = cursor.getString(pathIndex);
+            cursor.close();
+        } else {
+            throw new IllegalArgumentException("Given Uri scheme is not supported");
         }
-        String[] projection = new String[] {MediaStore.MediaColumns.DATA};
-        Cursor cursor = mContext.getContentResolver().query(uri, projection, null, null, null);
-        if (null == cursor || 0 == cursor.getCount() || !cursor.moveToFirst()) {
-            throw new IllegalArgumentException("Given Uri could not be found in media store");
-        }
-        int pathIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
-        String path = cursor.getString(pathIndex);
-        cursor.close();
         return path;
     }
 
     // private native interfaces
-    private native int _loadPlugIns(int uniqueId, Object weak_this);
+    private native void _initialize(int uniqueId, Object weak_this);
 
-    private native int _unloadPlugIns(int uniqueId);
+    private native void _finalize(int uniqueId);
 
     private native void _installDrmEngine(int uniqueId, String engineFilepath);
 
diff --git a/drm/java/android/drm/DrmUtils.java b/drm/java/android/drm/DrmUtils.java
index 5e5397c..8903485 100644
--- a/drm/java/android/drm/DrmUtils.java
+++ b/drm/java/android/drm/DrmUtils.java
@@ -167,6 +167,9 @@
 
                 //Fetch Value
                 String strValue = readMultipleBytes(constraintData, valueLength, index);
+                if (strValue.equals(" ")) {
+                    strValue = "";
+                }
                 index += valueLength;
                 mMap.put(strKey, strValue);
             }
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index 6158b66..e5e4547 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -15,7 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "DrmManager-JNI"
+#define LOG_TAG "android_drm_DrmManagerClient"
 #include <utils/Log.h>
 
 #include <jni.h>
@@ -223,38 +223,32 @@
     return sp<DrmManagerClientImpl>(client);
 }
 
-static jint android_drm_DrmManagerClient_loadPlugIns(
+static void android_drm_DrmManagerClient_initialize(
         JNIEnv* env, jobject thiz, jint uniqueId, jobject weak_thiz) {
-    LOGV("load plugins - Enter");
+    LOGV("initialize - Enter");
 
     sp<DrmManagerClientImpl> drmManager = DrmManagerClientImpl::create(&uniqueId);
+    drmManager->addClient(uniqueId);
 
     // Set the listener to DrmManager
     sp<DrmManagerClient::OnInfoListener> listener = new JNIOnInfoListener(env, thiz, weak_thiz);
     drmManager->setOnInfoListener(uniqueId, listener);
 
     setDrmManagerClientImpl(env, thiz, drmManager);
-
-    LOGV("load plugins - Exit");
-    return getDrmManagerClientImpl(env, thiz)->loadPlugIns(uniqueId);
+    LOGV("initialize - Exit");
 }
 
-static jint android_drm_DrmManagerClient_unloadPlugIns(JNIEnv* env, jobject thiz, jint uniqueId) {
-    LOGV("unload plugins - Enter");
-    sp<DrmManagerClientImpl> client = getDrmManagerClientImpl(env, thiz);
-
+static void android_drm_DrmManagerClient_finalize(JNIEnv* env, jobject thiz, jint uniqueId) {
+    LOGV("finalize - Enter");
     DrmManagerClientImpl::remove(uniqueId);
-    int result = client->unloadPlugIns(uniqueId);
-    if (DRM_NO_ERROR == result) {
-        client->setOnInfoListener(uniqueId, NULL);
+    getDrmManagerClientImpl(env, thiz)->setOnInfoListener(uniqueId, NULL);
 
-        sp<DrmManagerClientImpl> oldClient = setDrmManagerClientImpl(env, thiz, NULL);
-        if (oldClient != NULL) {
-            oldClient->setOnInfoListener(uniqueId, NULL);
-        }
+    sp<DrmManagerClientImpl> oldClient = setDrmManagerClientImpl(env, thiz, NULL);
+    if (oldClient != NULL) {
+        oldClient->setOnInfoListener(uniqueId, NULL);
+        oldClient->removeClient(uniqueId);
     }
-    LOGV("unload plugins - Exit");
-    return result;
+    LOGV("finalize - Exit");
 }
 
 static jobject android_drm_DrmManagerClient_getConstraintsFromContent(
@@ -441,6 +435,7 @@
 
     if (NULL != localRef && NULL != pDrmInfoStatus) {
         int statusCode = pDrmInfoStatus->statusCode;
+        int infoType = pDrmInfoStatus->infoType;
 
         jbyteArray dataArray = NULL;
         if (NULL != pDrmInfoStatus->drmBuffer) {
@@ -461,10 +456,10 @@
 
         constructorId
             = env->GetMethodID(localRef,
-                "<init>", "(ILandroid/drm/ProcessedData;Ljava/lang/String;)V");
+                "<init>", "(IILandroid/drm/ProcessedData;Ljava/lang/String;)V");
 
-        drmInfoStatus = env->NewObject(localRef, constructorId, statusCode, processedData,
-                                env->NewStringUTF(pDrmInfoStatus->mimeType.string()));
+        drmInfoStatus = env->NewObject(localRef, constructorId, statusCode, infoType,
+                processedData, env->NewStringUTF(pDrmInfoStatus->mimeType.string()));
     }
 
     delete mData; mData = NULL;
@@ -678,11 +673,11 @@
 
 static JNINativeMethod nativeMethods[] = {
 
-    {"_loadPlugIns", "(ILjava/lang/Object;)I",
-                                    (void*)android_drm_DrmManagerClient_loadPlugIns},
+    {"_initialize", "(ILjava/lang/Object;)V",
+                                    (void*)android_drm_DrmManagerClient_initialize},
 
-    {"_unloadPlugIns", "(I)I",
-                                    (void*)android_drm_DrmManagerClient_unloadPlugIns},
+    {"_finalize", "(I)V",
+                                    (void*)android_drm_DrmManagerClient_finalize},
 
     {"_getConstraints", "(ILjava/lang/String;I)Landroid/content/ContentValues;",
                                     (void*)android_drm_DrmManagerClient_getConstraintsFromContent},
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index c996994..f0439eb 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -22,36 +22,23 @@
 
 using namespace android;
 
-DrmManagerClient::DrmManagerClient() {
-    int uniqueId = 0;
-    mDrmManagerClientImpl = NULL;
-
-    mDrmManagerClientImpl = DrmManagerClientImpl::create(&uniqueId);
-    mUniqueId = uniqueId;
-
-    loadPlugIns();
+DrmManagerClient::DrmManagerClient():
+        mUniqueId(0), mDrmManagerClientImpl(NULL) {
+    mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId);
+    mDrmManagerClientImpl->addClient(mUniqueId);
 }
 
 DrmManagerClient::~DrmManagerClient() {
     DrmManagerClientImpl::remove(mUniqueId);
-    unloadPlugIns();
-
+    mDrmManagerClientImpl->removeClient(mUniqueId);
     delete mDrmManagerClientImpl; mDrmManagerClientImpl = NULL;
 }
 
-status_t DrmManagerClient::loadPlugIns() {
-    return mDrmManagerClientImpl->loadPlugIns(mUniqueId);
-}
-
 status_t DrmManagerClient::setOnInfoListener(
                     const sp<DrmManagerClient::OnInfoListener>& infoListener) {
     return mDrmManagerClientImpl->setOnInfoListener(mUniqueId, infoListener);
 }
 
-status_t DrmManagerClient::unloadPlugIns() {
-    return mDrmManagerClientImpl->unloadPlugIns(mUniqueId);
-}
-
 DrmConstraints* DrmManagerClient::getConstraints(const String8* path, const int action) {
     return mDrmManagerClientImpl->getConstraints(mUniqueId, path, action);
 }
@@ -86,6 +73,7 @@
 }
 
 status_t DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) {
+    Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
 }
 
@@ -128,12 +116,17 @@
     return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length);
 }
 
+DecryptHandle* DrmManagerClient::openDecryptSession(const char* uri) {
+    return mDrmManagerClientImpl->openDecryptSession(mUniqueId, uri);
+}
+
 status_t DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) {
     return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
 }
 
 status_t DrmManagerClient::initializeDecryptUnit(
             DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+    Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->initializeDecryptUnit(
             mUniqueId, decryptHandle, decryptUnitId, headerInfo);
 }
@@ -141,16 +134,19 @@
 status_t DrmManagerClient::decrypt(
     DecryptHandle* decryptHandle, int decryptUnitId,
     const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+    Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->decrypt(
             mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
 }
 
 status_t DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) {
+    Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId);
 }
 
 ssize_t DrmManagerClient::pread(
             DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) {
+    Mutex::Autolock _l(mDecryptLock);
     return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
 }
 
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index 272adcd..b3ae9a7 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -46,14 +46,6 @@
     getDrmManagerService()->removeUniqueId(uniqueId);
 }
 
-DrmManagerClientImpl::DrmManagerClientImpl() {
-
-}
-
-DrmManagerClientImpl::~DrmManagerClientImpl() {
-
-}
-
 const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
     mMutex.lock();
     if (NULL == mDrmManagerService.get()) {
@@ -77,16 +69,12 @@
     return mDrmManagerService;
 }
 
-status_t DrmManagerClientImpl::loadPlugIns(int uniqueId) {
-    return getDrmManagerService()->loadPlugIns(uniqueId);
+void DrmManagerClientImpl::addClient(int uniqueId) {
+    getDrmManagerService()->addClient(uniqueId);
 }
 
-status_t DrmManagerClientImpl::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
-    status_t status = DRM_ERROR_UNKNOWN;
-    if (EMPTY_STRING != plugInDirPath) {
-        status = getDrmManagerService()->loadPlugIns(uniqueId, plugInDirPath);
-    }
-    return status;
+void DrmManagerClientImpl::removeClient(int uniqueId) {
+    getDrmManagerService()->removeClient(uniqueId);
 }
 
 status_t DrmManagerClientImpl::setOnInfoListener(
@@ -96,10 +84,6 @@
     return getDrmManagerService()->setDrmServiceListener(uniqueId, this);
 }
 
-status_t DrmManagerClientImpl::unloadPlugIns(int uniqueId) {
-    return getDrmManagerService()->unloadPlugIns(uniqueId);
-}
-
 status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
     status_t status = DRM_ERROR_UNKNOWN;
     if (EMPTY_STRING != drmEngineFile) {
@@ -251,6 +235,14 @@
     return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length);
 }
 
+DecryptHandle* DrmManagerClientImpl::openDecryptSession(int uniqueId, const char* uri) {
+    DecryptHandle* handle = NULL;
+    if (NULL != uri) {
+        handle = getDrmManagerService()->openDecryptSession(uniqueId, uri);
+    }
+    return handle;
+}
+
 status_t DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
     status_t status = DRM_ERROR_UNKNOWN;
     if (NULL != decryptHandle) {
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index dc3e460..d782f5b 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -57,15 +57,19 @@
 
     void removeUniqueId(int uniqueId);
 
-    status_t loadPlugIns(int uniqueId);
+    void addClient(int uniqueId);
 
-    status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+    void removeClient(int uniqueId);
+
+    status_t loadPlugIns();
+
+    status_t loadPlugIns(const String8& plugInDirPath);
+
+    status_t unloadPlugIns();
 
     status_t setDrmServiceListener(
             int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
 
-    status_t unloadPlugIns(int uniqueId);
-
     status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
 
     DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
@@ -107,6 +111,8 @@
 
     DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
 
+    DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
     status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
 
     status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
@@ -129,12 +135,8 @@
 
     String8 getSupportedPlugInIdFromPath(int uniqueId, const String8& path);
 
-    void populate(int uniqueId);
-
     bool canHandle(int uniqueId, const String8& path);
 
-    void initializePlugIns(int uniqueId);
-
 private:
     static Vector<int> mUniqueIdVector;
     static const String8 EMPTY_STRING;
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 492c7f5..1c6be46 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -35,36 +35,29 @@
  */
 class DrmManagerClientImpl : public BnDrmServiceListener {
 private:
-    DrmManagerClientImpl();
+    DrmManagerClientImpl() { }
 
 public:
     static DrmManagerClientImpl* create(int* pUniqueId);
 
     static void remove(int uniqueId);
 
-    virtual ~DrmManagerClientImpl();
+    virtual ~DrmManagerClientImpl() { }
 
 public:
     /**
-     * Initialize DRM Manager
-     *     load available plug-ins from default plugInDirPath
+     * Adds the client respective to given unique id.
      *
      * @param[in] uniqueId Unique identifier for a session
-     * @return status_t
-     *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t loadPlugIns(int uniqueId);
+    void addClient(int uniqueId);
 
     /**
-     * Finalize DRM Manager
-     *     release resources associated with each plug-in
-     *     unload all plug-ins and etc.
+     * Removes the client respective to given unique id.
      *
      * @param[in] uniqueId Unique identifier for a session
-     * @return status_t
-     *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
      */
-    status_t unloadPlugIns(int uniqueId);
+    void removeClient(int uniqueId);
 
     /**
      * Register a callback to be invoked when the caller required to
@@ -301,6 +294,16 @@
     DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
 
     /**
+     * Open the decrypt session to decrypt the given protected content
+     *
+     * @param[in] uniqueId Unique identifier for a session
+     * @param[in] uri Path of the protected content to be decrypted
+     * @return
+     *     Handle for the decryption session
+     */
+    DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
+    /**
      * Close the decrypt session for the given handle
      *
      * @param[in] uniqueId Unique identifier for a session
@@ -379,17 +382,6 @@
 
 private:
     /**
-     * Initialize DRM Manager
-     *     load available plug-ins from plugInDirPath
-     *
-     * @param[in] uniqueId Unique identifier for a session
-     * @param[in] plugInDirPath Directory from where to load plug-ins
-     * @return status_t
-     *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
-     */
-    status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
-
-    /**
      * Install new DRM Engine Plug-in at the runtime
      *
      * @param[in] uniqueId Unique identifier for a session
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index f455e15..4a3aeae 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -50,15 +50,13 @@
 
     void removeUniqueId(int uniqueId);
 
-    status_t loadPlugIns(int uniqueId);
+    void addClient(int uniqueId);
 
-    status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+    void removeClient(int uniqueId);
 
     status_t setDrmServiceListener(
             int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
 
-    status_t unloadPlugIns(int uniqueId);
-
     status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
 
     DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
@@ -100,6 +98,8 @@
 
     DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
 
+    DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
     status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
 
     status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 5c668ed..1275488 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -46,10 +46,9 @@
     enum {
         ADD_UNIQUEID = IBinder::FIRST_CALL_TRANSACTION,
         REMOVE_UNIQUEID,
-        LOAD_PLUGINS,
-        LOAD_PLUGINS_FROM_PATH,
+        ADD_CLIENT,
+        REMOVE_CLIENT,
         SET_DRM_SERVICE_LISTENER,
-        UNLOAD_PLUGINS,
         INSTALL_DRM_ENGINE,
         GET_CONSTRAINTS_FROM_CONTENT,
         CAN_HANDLE,
@@ -69,6 +68,7 @@
         CLOSE_CONVERT_SESSION,
         GET_ALL_SUPPORT_INFO,
         OPEN_DECRYPT_SESSION,
+        OPEN_DECRYPT_SESSION_FROM_URI,
         CLOSE_DECRYPT_SESSION,
         INITIALIZE_DECRYPT_UNIT,
         DECRYPT,
@@ -84,15 +84,13 @@
 
     virtual void removeUniqueId(int uniqueId) = 0;
 
-    virtual status_t loadPlugIns(int uniqueId) = 0;
+    virtual void addClient(int uniqueId) = 0;
 
-    virtual status_t loadPlugIns(int uniqueId, const String8& plugInDirPath) = 0;
+    virtual void removeClient(int uniqueId) = 0;
 
     virtual status_t setDrmServiceListener(
             int uniqueId, const sp<IDrmServiceListener>& infoListener) = 0;
 
-    virtual status_t unloadPlugIns(int uniqueId) = 0;
-
     virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile) = 0;
 
     virtual DrmConstraints* getConstraints(
@@ -140,6 +138,8 @@
 
     virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length) = 0;
 
+    virtual DecryptHandle* openDecryptSession(int uniqueId, const char* uri) = 0;
+
     virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
 
     virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
@@ -168,15 +168,13 @@
 
     virtual void removeUniqueId(int uniqueId);
 
-    virtual status_t loadPlugIns(int uniqueId);
+    virtual void addClient(int uniqueId);
 
-    virtual status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+    virtual void removeClient(int uniqueId);
 
     virtual status_t setDrmServiceListener(
             int uniqueId, const sp<IDrmServiceListener>& infoListener);
 
-    virtual status_t unloadPlugIns(int uniqueId);
-
     virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
 
     virtual DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
@@ -221,6 +219,8 @@
 
     virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
 
+    virtual DecryptHandle* openDecryptSession(int uniqueId, const char* uri);
+
     virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
 
     virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index b355534..5851af5 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -80,6 +80,9 @@
     status_t openDecryptSession(
             int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length);
 
+    status_t openDecryptSession(
+            int uniqueId, DecryptHandle* decryptHandle, const char* uri);
+
     status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
 
     status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
@@ -355,6 +358,18 @@
             int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0;
 
     /**
+     * Open the decrypt session to decrypt the given protected content
+     *
+     * @param[in] uniqueId Unique identifier for a session
+     * @param[in] decryptHandle Handle for the current decryption session
+     * @param[in] uri Path of the protected content to be decrypted
+     * @return
+     *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+     */
+    virtual status_t onOpenDecryptSession(
+            int uniqueId, DecryptHandle* decryptHandle, const char* uri) = 0;
+
+    /**
      * Close the decrypt session for the given handle
      *
      * @param[in] uniqueId Unique identifier for a session
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
index b711500..cc03ef2 100644
--- a/drm/libdrmframework/plugins/common/include/IDrmEngine.h
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -315,6 +315,18 @@
         int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0;
 
     /**
+     * Open the decrypt session to decrypt the given protected content
+     *
+     * @param[in] uniqueId Unique identifier for a session
+     * @param[in] decryptHandle Handle for the current decryption session
+     * @param[in] uri Path of the protected content to be decrypted
+     * @return
+     *     DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+     */
+    virtual status_t openDecryptSession(
+        int uniqueId, DecryptHandle* decryptHandle, const char* uri) = 0;
+
+    /**
      * Close the decrypt session for the given handle
      *
      * @param[in] uniqueId Unique identifier for a session
diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
index eed1628..ddb7fd3 100644
--- a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
+++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
@@ -74,6 +74,9 @@
     status_t onOpenDecryptSession(
             int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length);
 
+    status_t onOpenDecryptSession(
+            int uniqueId, DecryptHandle* decryptHandle, const char* uri);
+
     status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
 
     status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
index 4c7714de..41f8e91 100644
--- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -74,14 +74,14 @@
         switch (drmInfo->getInfoType()) {
         case DrmInfoRequest::TYPE_REGISTRATION_INFO: {
             const DrmBuffer* emptyBuffer = new DrmBuffer();
-            drmInfoStatus
-                = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, emptyBuffer, drmInfo->getMimeType());
+            drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+                    DrmInfoRequest::TYPE_REGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType());
             break;
         }
         case DrmInfoRequest::TYPE_UNREGISTRATION_INFO: {
             const DrmBuffer* emptyBuffer = new DrmBuffer();
-            drmInfoStatus
-                = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, emptyBuffer, drmInfo->getMimeType());
+            drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+                    DrmInfoRequest::TYPE_UNREGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType());
             break;
         }
         case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: {
@@ -91,8 +91,8 @@
             data = new char[bufferSize];
             memcpy(data, licenseString.string(), bufferSize);
             const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
-            drmInfoStatus
-                = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, buffer, drmInfo->getMimeType());
+            drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+                    DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType());
             break;
         }
         }
@@ -243,6 +243,11 @@
     return DRM_ERROR_CANNOT_HANDLE;
 }
 
+status_t DrmPassthruPlugIn::onOpenDecryptSession(
+            int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
+    return DRM_ERROR_CANNOT_HANDLE;
+}
+
 status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
     LOGD("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
     if (NULL != decryptHandle) {
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
index c722bd3..7b409ff 100644
--- a/include/drm/DrmInfoEvent.h
+++ b/include/drm/DrmInfoEvent.h
@@ -59,8 +59,8 @@
     //! TYPE_NO_INTERNET_CONNECTION, when the Internet connection is missing and no attempt
     //! can be made to renew rights
     static const int TYPE_NO_INTERNET_CONNECTION = 2005;
-    //! TYPE_REGISTRATION_FAILED, when registration with server failed.
-    static const int TYPE_REGISTRATION_FAILED = 2006;
+    //! TYPE_PROCESS_DRM_INFO_FAILED, when failed to process DrmInfo.
+    static const int TYPE_PROCESS_DRM_INFO_FAILED = 2006;
 
 public:
     /**
diff --git a/include/drm/DrmInfoStatus.h b/include/drm/DrmInfoStatus.h
index 806aea1..88c0f40 100644
--- a/include/drm/DrmInfoStatus.h
+++ b/include/drm/DrmInfoStatus.h
@@ -41,10 +41,11 @@
      * Constructor for DrmInfoStatus
      *
      * @param[in] _statusCode Status of the communication
+     * @param[in] _infoType Type of the DRM information processed
      * @param[in] _drmBuffer Rights information
      * @param[in] _mimeType MIME type
      */
-    DrmInfoStatus(int _statusCode, const DrmBuffer* _drmBuffer, const String8& _mimeType);
+    DrmInfoStatus(int _statusCode, int _infoType, const DrmBuffer* _drmBuffer, const String8& _mimeType);
 
     /**
      * Destructor for DrmInfoStatus
@@ -55,6 +56,7 @@
 
 public:
     int statusCode;
+    int infoType;
     const DrmBuffer* drmBuffer;
     String8 mimeType;
 };
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
index c2ad084..5963c42 100644
--- a/include/drm/DrmManagerClient.h
+++ b/include/drm/DrmManagerClient.h
@@ -17,6 +17,7 @@
 #ifndef __DRM_MANAGER_CLIENT_H__
 #define __DRM_MANAGER_CLIENT_H__
 
+#include <utils/threads.h>
 #include <binder/IInterface.h>
 #include "drm_framework_common.h"
 
@@ -67,6 +68,15 @@
     DecryptHandle* openDecryptSession(int fd, int offset, int length);
 
     /**
+     * Open the decrypt session to decrypt the given protected content
+     *
+     * @param[in] uri Path of the protected content to be decrypted
+     * @return
+     *     Handle for the decryption session
+     */
+    DecryptHandle* openDecryptSession(const char* uri);
+
+    /**
      * Close the decrypt session for the given handle
      *
      * @param[in] decryptHandle Handle for the decryption session
@@ -339,27 +349,8 @@
     status_t getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray);
 
 private:
-    /**
-     * Initialize DRM Manager
-     *     load available plug-ins from default plugInDirPath
-     *
-     * @return status_t
-     *     Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
-     */
-    status_t loadPlugIns();
-
-    /**
-     * Finalize DRM Manager
-     *    release resources associated with each plug-in
-     *    unload all plug-ins and etc.
-     *
-     * @return status_t
-     *    Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
-     */
-    status_t unloadPlugIns();
-
-private:
     int mUniqueId;
+    Mutex mDecryptLock;
     DrmManagerClientImpl* mDrmManagerClientImpl;
 };
 
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index 8ea3ab9..e9c7df2 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -29,6 +29,7 @@
 
 #include <ui/egl/android_natives.h>
 
+#define NUM_FRAME_BUFFERS  2
 
 extern "C" EGLNativeWindowType android_createDisplaySurface(void);
 
@@ -69,7 +70,7 @@
     framebuffer_device_t* fbDev;
     alloc_device_t* grDev;
 
-    sp<NativeBuffer> buffers[2];
+    sp<NativeBuffer> buffers[NUM_FRAME_BUFFERS];
     sp<NativeBuffer> front;
     
     mutable Mutex mutex;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 52380a0..c43fac1 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -82,6 +82,7 @@
     if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
         int stride;
         int err;
+        int i;
         err = framebuffer_open(module, &fbDev);
         LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
         
@@ -95,27 +96,33 @@
         mUpdateOnDemand = (fbDev->setUpdateRect != 0);
         
         // initialize the buffer FIFO
-        mNumBuffers = 2;
-        mNumFreeBuffers = 2;
+        mNumBuffers = NUM_FRAME_BUFFERS;
+        mNumFreeBuffers = NUM_FRAME_BUFFERS;
         mBufferHead = mNumBuffers-1;
-        buffers[0] = new NativeBuffer(
-                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
-        buffers[1] = new NativeBuffer(
-                fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
-        
-        err = grDev->alloc(grDev,
-                fbDev->width, fbDev->height, fbDev->format, 
-                GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride);
 
-        LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
-                fbDev->width, fbDev->height, strerror(-err));
+        for (i = 0; i < mNumBuffers; i++)
+        {
+                buffers[i] = new NativeBuffer(
+                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
+        }
 
-        err = grDev->alloc(grDev,
-                fbDev->width, fbDev->height, fbDev->format, 
-                GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
+        for (i = 0; i < mNumBuffers; i++)
+        {
+                err = grDev->alloc(grDev,
+                        fbDev->width, fbDev->height, fbDev->format,
+                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
 
-        LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
-                fbDev->width, fbDev->height, strerror(-err));
+                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
+                        i, fbDev->width, fbDev->height, strerror(-err));
+
+                if (err)
+                {
+                        mNumBuffers = i;
+                        mNumFreeBuffers = i;
+                        mBufferHead = mNumBuffers-1;
+                        break;
+                }
+        }
 
         const_cast<uint32_t&>(android_native_window_t::flags) = fbDev->flags; 
         const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7bbc9eb..9789e36 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -288,14 +288,9 @@
     }
 
     dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
-    if (mDecryptHandle != NULL) {
-        if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
-            if (DecryptApiType::CONTAINER_BASED == mDecryptHandle->decryptApiType) {
-                mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true);
-            }
-        } else {
-            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
-        }
+    if (mDecryptHandle != NULL
+            && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
     }
 
     return setDataSource_l(extractor);
@@ -328,11 +323,6 @@
     }
 
     mExtractorFlags = extractor->flags();
-    if (mDecryptHandle != NULL) {
-        if (DecryptApiType::ELEMENTARY_STREAM_BASED == mDecryptHandle->decryptApiType) {
-            mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true);
-        }
-    }
 
     return OK;
 }
@@ -346,8 +336,6 @@
     if (mDecryptHandle != NULL) {
             mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
                     Playback::STOP, 0);
-            mDrmManagerClient->consumeRights(mDecryptHandle,
-                    Action::PLAY, false);
             mDecryptHandle = NULL;
             mDrmManagerClient = NULL;
     }
@@ -1190,14 +1178,9 @@
     }
 
     dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
-    if (mDecryptHandle != NULL) {
-        if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
-            if (DecryptApiType::CONTAINER_BASED == mDecryptHandle->decryptApiType) {
-                mDrmManagerClient->consumeRights(mDecryptHandle, Action::PLAY, true);
-            }
-        } else {
-            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
-        }
+    if (mDecryptHandle != NULL
+            && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
     }
 
     if (dataSource->flags() & DataSource::kWantsPrefetching) {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index d7dd4e5..23c4790 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -28,6 +28,8 @@
 #include <media/stagefright/MediaErrors.h>
 #include <utils/String8.h>
 
+#include <cutils/properties.h>
+
 namespace android {
 
 bool DataSource::getUInt16(off_t offset, uint16_t *x) {
@@ -95,7 +97,12 @@
     RegisterSniffer(SniffAMR);
     RegisterSniffer(SniffWAV);
     RegisterSniffer(SniffOgg);
-    RegisterSniffer(SniffDRM);
+
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("drm.service.enabled", value, NULL)
+            && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+        RegisterSniffer(SniffDRM);
+    }
 }
 
 // static
diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java
index 07a3a53..d1476d2 100644
--- a/obex/javax/obex/ServerOperation.java
+++ b/obex/javax/obex/ServerOperation.java
@@ -397,11 +397,13 @@
                     && (headerID != ObexHelper.OBEX_OPCODE_GET_FINAL)) {
 
                 if (length > 3) {
-                    byte[] temp = new byte[length];
+                    byte[] temp = new byte[length - 3];
+                    // First three bytes already read, compensating for this
                     bytesReceived = mInput.read(temp);
 
-                    while (bytesReceived != length) {
-                        bytesReceived += mInput.read(temp, bytesReceived, length - bytesReceived);
+                    while (bytesReceived != temp.length) {
+                        bytesReceived += mInput.read(temp, bytesReceived,
+                                temp.length - bytesReceived);
                     }
                 }
 
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index cb55808..542c740 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -958,6 +958,17 @@
             // Post a unmount message.
             ShutdownCallBack ucb = new ShutdownCallBack(path, observer);
             mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
+        } else if (observer != null) {
+            /*
+             * Observer is waiting for onShutDownComplete when we are done.
+             * Since nothing will be done send notification directly so shutdown
+             * sequence can continue.
+             */
+            try {
+                observer.onShutDownComplete(StorageResultCode.OperationSucceeded);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "RemoteException when shutting down");
+            }
         }
     }
 
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index a2f085a..82c143d 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1629,13 +1629,6 @@
     
     // If a parent is explicitly specified, set it.
     if (bagParent.size() > 0) {
-        String16 curPar = e->getParent();
-        if (curPar.size() > 0 && curPar != bagParent) {
-            sourcePos.error("Conflicting parents specified, was '%s', now '%s'\n",
-                            String8(e->getParent()).string(),
-                            String8(bagParent).string());
-            return UNKNOWN_ERROR;
-        }
         e->setParent(bagParent);
     }
 
@@ -1683,13 +1676,6 @@
 
     // If a parent is explicitly specified, set it.
     if (bagParent.size() > 0) {
-        String16 curPar = e->getParent();
-        if (curPar.size() > 0 && curPar != bagParent) {
-            sourcePos.error("Conflicting parents specified, was '%s', now '%s'\n",
-                    String8(e->getParent()).string(),
-                    String8(bagParent).string());
-            return UNKNOWN_ERROR;
-        }
         e->setParent(bagParent);
     }