Merge "Add matrix component types. Fix potental overflow in script -> java messages."
diff --git a/api/current.xml b/api/current.xml
index 8ff263c..619b257 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -51208,6 +51208,17 @@
 <parameter name="key" type="java.lang.String">
 </parameter>
 </method>
+<method name="startCommit"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </interface>
 <interface name="SharedPreferences.OnSharedPreferenceChangeListener"
  abstract="true"
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e34bad2..fee95aa 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2878,6 +2878,11 @@
                 }
             }
 
+            public void startCommit() {
+                // TODO: implement
+                commit();
+            }
+
             public boolean commit() {
                 boolean returnValue;
 
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 5847216..6ee716a 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -163,14 +163,47 @@
          * {@link SharedPreferences} object it is editing.  This atomically
          * performs the requested modifications, replacing whatever is currently
          * in the SharedPreferences.
-         * 
+         *
          * <p>Note that when two editors are modifying preferences at the same
          * time, the last one to call commit wins.
-         * 
+         *
+         * <p>If you don't care about the return value and you're
+         * using this from your application's main thread, consider
+         * using {@link #startCommit} instead.
+         *
          * @return Returns true if the new values were successfully written
          * to persistent storage.
          */
         boolean commit();
+
+        /**
+         * Commit your preferences changes back from this Editor to the
+         * {@link SharedPreferences} object it is editing.  This atomically
+         * performs the requested modifications, replacing whatever is currently
+         * in the SharedPreferences.
+         *
+         * <p>Note that when two editors are modifying preferences at the same
+         * time, the last one to call commit wins.
+         *
+         * <p>Unlike {@link #commit}, which writes its preferences out
+         * to persistent storage synchronously, {@link #startCommit}
+         * commits its changes to the in-memory
+         * {@link SharedPreferences} immediately but starts an
+         * asynchronous commit to disk and you won't be notified of
+         * any failures.  If another editor on this
+         * {@link SharedPreferences} does a regular {@link #commit}
+         * while a {@link #startCommit} is still outstanding, the
+         * {@link #commit} will block until all async commits are
+         * completed as well as the commit itself.
+         *
+         * <p>If you call this from an {@link android.app.Activity},
+         * the base class will wait for any async commits to finish in
+         * its {@link android.app.Activity#onPause}.</p>
+         *
+         * @return Returns true if the new values were successfully written
+         * to persistent storage.
+         */
+        void startCommit();
     }
 
     /**
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 97921fe..0068724 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -34,11 +34,19 @@
 import java.util.List;
 
 /**
+ * <p>
  * SensorManager lets you access the device's {@link android.hardware.Sensor
  * sensors}. Get an instance of this class by calling
  * {@link android.content.Context#getSystemService(java.lang.String)
  * Context.getSystemService()} with the argument
  * {@link android.content.Context#SENSOR_SERVICE}.
+ * </p>
+ * <p>
+ * Always make sure to disable sensors you don't need, especially when your
+ * activity is paused. Failing to do so can drain the battery in just a few
+ * hours. Note that the system will <i>not</i> disable sensors automatically when
+ * the screen turns off.
+ * </p>
  *
  * <pre class="prettyprint">
  * public class SensorActivity extends Activity, implements SensorEventListener {
@@ -48,13 +56,22 @@
  *     public SensorActivity() {
  *         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
  *         mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ *     }
+ *
+ *     protected void onResume() {
+ *         super.onResume();
  *         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
  *     }
  *
+ *     protected void onPause() {
+ *         super.onPause();
+ *         mSensorManager.unregisterListener(this);
+ *     }
+ *
  *     public void onAccuracyChanged(Sensor sensor, int accuracy) {
  *     }
  *
- *     public abstract void onSensorChanged(SensorEvent event) {
+ *     public void onSensorChanged(SensorEvent event) {
  *     }
  * }
  * </pre>
diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java
index bc764ac..26aa7d8 100644
--- a/core/java/android/provider/Mtp.java
+++ b/core/java/android/provider/Mtp.java
@@ -311,9 +311,12 @@
         // Object properties we support
         public static final int PROPERTY_STORAGE_ID = 0xDC01;
         public static final int PROPERTY_OBJECT_FORMAT = 0xDC02;
+        public static final int PROPERTY_PROTECTION_STATUS = 0xDC03;
         public static final int PROPERTY_OBJECT_SIZE = 0xDC04;
         public static final int PROPERTY_OBJECT_FILE_NAME = 0xDC07;
+        public static final int PROPERTY_DATE_MODIFIED = 0xDC09;
         public static final int PROPERTY_PARENT_OBJECT = 0xDC0B;
+        public static final int PROPERTY_PERSISTENT_UID = 0xDC41;
 
         /**
          * Object is not protected. It may be modified and deleted, and its properties
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 32d8123..42e3641 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -53,8 +53,10 @@
 
     /**
      * Destroys the hardware rendering context.
+     * 
+     * @param full If true, destroys all associated resources.
      */
-    abstract void destroy();
+    abstract void destroy(boolean full);
 
     /**
      * Initializes the hardware renderer for the specified surface.
@@ -187,7 +189,7 @@
         }
 
         /**
-         * Checks for OpenGL errors. If an error has occured, {@link #destroy()}
+         * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
          * is invoked and the requested flag is turned off. The error code is
          * also logged as a warning.
          */
@@ -197,7 +199,7 @@
                 if (error != EGL10.EGL_SUCCESS) {
                     // something bad has happened revert to
                     // normal rendering.
-                    destroy();
+                    destroy(true);
                     if (error != EGL11.EGL_CONTEXT_LOST) {
                         // we'll try again if it was context lost
                         setRequested(false);
@@ -217,13 +219,12 @@
                 if (mGl != null) {
                     int err = sEgl.eglGetError();
                     if (err != EGL10.EGL_SUCCESS) {
-                        destroy();
+                        destroy(true);
                         setRequested(false);
                     } else {
-                        if (mCanvas != null) {
-                            destroyCanvas();
+                        if (mCanvas == null) {
+                            mCanvas = createCanvas();
                         }
-                        mCanvas = createCanvas();
                         if (mCanvas != null) {
                             setEnabled(true);
                         } else {
@@ -237,11 +238,6 @@
             return false;
         }
 
-        private void destroyCanvas() {
-            mCanvas.destroy();
-            mCanvas = null;
-        }
-
         abstract GLES20Canvas createCanvas();
 
         void initializeEgl() {
@@ -341,16 +337,16 @@
         }
         
         @Override
-        void destroy() {
+        void destroy(boolean full) {
+            if (full && mCanvas != null) {
+                mCanvas.destroy();
+                mCanvas = null;
+            }
+            
             if (!isEnabled() || mDestroyed) return;
 
             mDestroyed = true;
 
-            checkCurrent();
-            // Destroy the Canvas first in case it needs to use a GL context
-            // to perform its cleanup.
-            destroyCanvas();
-
             sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
                     EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
             sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
@@ -358,12 +354,6 @@
             mEglSurface = null;
             mGl = null;
 
-            // mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-            // mEglContext = null;            
-            // mEgl.eglTerminate(mEglDisplay);
-            // mEgl = null;
-            // mEglDisplay = null;
-
             setEnabled(false);
         }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 5999aba..a91d2bd 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -469,7 +469,9 @@
             if (attrs != null &&
                     (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE;
-                destroyHardwareRenderer();
+                if (mHwRenderer != null) {
+                    mHwRenderer.destroy(true);
+                }                
                 mHwRenderer = HardwareRenderer.createGlRenderer(2, translucent);
             }
         }
@@ -678,7 +680,9 @@
             attachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
-                destroyHardwareRenderer();
+                if (mHwRenderer != null) {
+                    mHwRenderer.destroy(false);
+                }                
             }
             if (viewVisibility == View.GONE) {
                 // After making a window gone, we will count it as being
@@ -1597,9 +1601,11 @@
         mAttachInfo.mRootView = null;
         mAttachInfo.mSurface = null;
 
-        destroyHardwareRenderer();
-        mHwRenderer = null;
-        
+        if (mHwRenderer != null) {
+            mHwRenderer.destroy(true);
+            mHwRenderer = null;
+        }
+
         mSurface.release();
 
         if (mInputChannel != null) {
@@ -1624,12 +1630,6 @@
         }
     }
 
-    private void destroyHardwareRenderer() {
-        if (mHwRenderer != null) {
-            mHwRenderer.destroy();
-        }
-    }
-
     void updateConfiguration(Configuration config, boolean force) {
         if (DEBUG_CONFIGURATION) Log.v(TAG,
                 "Applying new config to window "
diff --git a/core/res/res/values-rm/donottranslate-cldr.xml b/core/res/res/values-rm/donottranslate-cldr.xml
new file mode 100644
index 0000000..4b9f9db
--- /dev/null
+++ b/core/res/res/values-rm/donottranslate-cldr.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="month_long_standalone_january">schaner</string>
+    <string name="month_long_standalone_february">favrer</string>
+    <string name="month_long_standalone_march">mars</string>
+    <string name="month_long_standalone_april">avrigl</string>
+    <string name="month_long_standalone_may">matg</string>
+    <string name="month_long_standalone_june">zercladur</string>
+    <string name="month_long_standalone_july">fanadur</string>
+    <string name="month_long_standalone_august">avust</string>
+    <string name="month_long_standalone_september">settember</string>
+    <string name="month_long_standalone_october">october</string>
+    <string name="month_long_standalone_november">november</string>
+    <string name="month_long_standalone_december">december</string>
+
+    <string name="month_long_january">schaner</string>
+    <string name="month_long_february">favrer</string>
+    <string name="month_long_march">mars</string>
+    <string name="month_long_april">avrigl</string>
+    <string name="month_long_may">matg</string>
+    <string name="month_long_june">zercladur</string>
+    <string name="month_long_july">fanadur</string>
+    <string name="month_long_august">avust</string>
+    <string name="month_long_september">settember</string>
+    <string name="month_long_october">october</string>
+    <string name="month_long_november">november</string>
+    <string name="month_long_december">december</string>
+
+    <string name="month_medium_january">schan.</string>
+    <string name="month_medium_february">favr.</string>
+    <string name="month_medium_march">mars</string>
+    <string name="month_medium_april">avr.</string>
+    <string name="month_medium_may">matg</string>
+    <string name="month_medium_june">zercl.</string>
+    <string name="month_medium_july">fan.</string>
+    <string name="month_medium_august">avust</string>
+    <string name="month_medium_september">sett.</string>
+    <string name="month_medium_october">oct.</string>
+    <string name="month_medium_november">nov.</string>
+    <string name="month_medium_december">dec.</string>
+
+    <string name="month_shortest_january">S</string>
+    <string name="month_shortest_february">F</string>
+    <string name="month_shortest_march">M</string>
+    <string name="month_shortest_april">A</string>
+    <string name="month_shortest_may">M</string>
+    <string name="month_shortest_june">Z</string>
+    <string name="month_shortest_july">F</string>
+    <string name="month_shortest_august">A</string>
+    <string name="month_shortest_september">S</string>
+    <string name="month_shortest_october">O</string>
+    <string name="month_shortest_november">N</string>
+    <string name="month_shortest_december">D</string>
+
+    <string name="sunday">dumengia</string>
+    <string name="monday">glindesdi</string>
+    <string name="tuesday">mardi</string>
+    <string name="wednesday">mesemna</string>
+    <string name="thursday">gievgia</string>
+    <string name="friday">venderdi</string>
+    <string name="saturday">sonda</string>
+
+    <string name="day_of_week_long_sunday">dumengia</string>
+    <string name="day_of_week_long_monday">glindesdi</string>
+    <string name="day_of_week_long_tuesday">mardi</string>
+    <string name="day_of_week_long_wednesday">mesemna</string>
+    <string name="day_of_week_long_thursday">gievgia</string>
+    <string name="day_of_week_long_friday">venderdi</string>
+    <string name="day_of_week_long_saturday">sonda</string>
+
+    <string name="day_of_week_medium_sunday">du</string>
+    <string name="day_of_week_medium_monday">gli</string>
+    <string name="day_of_week_medium_tuesday">ma</string>
+    <string name="day_of_week_medium_wednesday">me</string>
+    <string name="day_of_week_medium_thursday">gie</string>
+    <string name="day_of_week_medium_friday">ve</string>
+    <string name="day_of_week_medium_saturday">so</string>
+
+    <string name="day_of_week_short_sunday">du</string>
+    <string name="day_of_week_short_monday">gli</string>
+    <string name="day_of_week_short_tuesday">ma</string>
+    <string name="day_of_week_short_wednesday">me</string>
+    <string name="day_of_week_short_thursday">gie</string>
+    <string name="day_of_week_short_friday">ve</string>
+    <string name="day_of_week_short_saturday">so</string>
+
+    <string name="day_of_week_shorter_sunday">D</string>
+    <string name="day_of_week_shorter_monday">G</string>
+    <string name="day_of_week_shorter_tuesday">M</string>
+    <string name="day_of_week_shorter_wednesday">M</string>
+    <string name="day_of_week_shorter_thursday">G</string>
+    <string name="day_of_week_shorter_friday">V</string>
+    <string name="day_of_week_shorter_saturday">S</string>
+
+    <string name="day_of_week_shortest_sunday">D</string>
+    <string name="day_of_week_shortest_monday">G</string>
+    <string name="day_of_week_shortest_tuesday">M</string>
+    <string name="day_of_week_shortest_wednesday">M</string>
+    <string name="day_of_week_shortest_thursday">G</string>
+    <string name="day_of_week_shortest_friday">V</string>
+    <string name="day_of_week_shortest_saturday">S</string>
+
+    <string name="yesterday">ier</string>
+    <string name="today">oz</string>
+    <string name="tomorrow">damaun</string>
+
+    <string name="hour_minute_24">%-k:%M</string>
+    <string name="hour_minute_ampm">%-l:%M %p</string>
+    <string name="hour_minute_cap_ampm">%-l:%M %^p</string>
+    <string name="twelve_hour_time_format">h:mm a</string>
+    <string name="twenty_four_hour_time_format">H:mm</string>
+    <string name="numeric_date">%d.%m.%Y</string>
+    <string name="numeric_date_format">dd.MM.yyyy</string>
+    <string name="numeric_date_template">"%s.%s.%s"</string>
+    <string name="month_day_year">%-e. %B %Y</string>
+    <string name="full_date_month_first">d. MMMM y</string>
+    <string name="full_date_day_first">d. MMMM y</string>
+    <string name="medium_date_month_first">d. MMM y</string>
+    <string name="medium_date_day_first">d. MMM y</string>
+    <string name="time_of_day">%H:%M:%S</string>
+    <string name="status_bar_time_format">HH:mm</string>
+    <string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
+    <string name="date_time">%1$s, %2$s</string>
+    <string name="time_date">%3$s, %1$s</string>
+    <string name="abbrev_month_day_year">%d.%m.%Y</string>
+    <string name="month_day">%-e. %B</string>
+    <string name="month">%-B</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%-e. %b</string>
+    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_year">%b %Y</string>
+    <string name="time1_time2">%1$s - %2$s</string>
+    <string name="date1_date2">%2$s - %5$s</string>
+    <string name="numeric_md1_md2">%3$s.%2$s. - %8$s.%7$s.</string>
+    <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
+    <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
+    <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+    <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
+    <string name="time_wday_date">%1$s %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday">%1$s %2$s</string>
+    <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+    <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
+    <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+    <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
+    <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+    <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
+    <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
+    <string name="short_format_month">%b</string>
+</resources>
diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h
index 53205bb..a3f094c 100644
--- a/include/media/EffectPresetReverbApi.h
+++ b/include/media/EffectPresetReverbApi.h
@@ -43,7 +43,8 @@
     REVERB_PRESET_LARGEROOM,
     REVERB_PRESET_MEDIUMHALL,
     REVERB_PRESET_LARGEHALL,
-    REVERB_PRESET_PLATE
+    REVERB_PRESET_PLATE,
+    REVERB_PRESET_LAST = REVERB_PRESET_PLATE
 } t_reverb_presets;
 
 #if __cplusplus
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 88cce46..7e0d390 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -66,14 +66,6 @@
 
     private final MediaScanner mMediaScanner;
 
-    // MTP property codes
-    private static final int MTP_PROPERTY_STORAGE_ID = 0xDC01;
-    private static final int MTP_PROPERTY_OBJECT_FORMAT = 0xDC02;
-    private static final int MTP_PROPERTY_OBJECT_SIZE = 0xDC04;
-    private static final int MTP_PROPERTY_OBJECT_FILE_NAME = 0xDC07;
-    private static final int MTP_PROPERTY_DATE_MODIFIED = 0xDC09;
-    private static final int MTP_PROPERTY_PARENT_OBJECT = 0xDC0B;
-
     // MTP response codes
     private static final int MTP_RESPONSE_OK = 0x2001;
     private static final int MTP_RESPONSE_GENERAL_ERROR = 0x2002;
@@ -271,25 +263,36 @@
         boolean isString = false;
 
         switch (property) {
-            case MTP_PROPERTY_STORAGE_ID:
+            case Mtp.Object.PROPERTY_STORAGE_ID:
                 outIntValue[0] = mStorageID;
                 return MTP_RESPONSE_OK;
-            case MTP_PROPERTY_OBJECT_FORMAT:
+            case Mtp.Object.PROPERTY_OBJECT_FORMAT:
                 column = MtpObjects.ObjectColumns.FORMAT;
                 break;
-            case MTP_PROPERTY_OBJECT_SIZE:
+            case Mtp.Object.PROPERTY_PROTECTION_STATUS:
+                // protection status is always 0
+                outIntValue[0] = 0;
+                return MTP_RESPONSE_OK;
+            case Mtp.Object.PROPERTY_OBJECT_SIZE:
                 column = MtpObjects.ObjectColumns.SIZE;
                 break;
-            case MTP_PROPERTY_OBJECT_FILE_NAME:
+            case Mtp.Object.PROPERTY_OBJECT_FILE_NAME:
                 column = MtpObjects.ObjectColumns.DATA;
                 isString = true;
                 break;
-            case MTP_PROPERTY_DATE_MODIFIED:
+            case Mtp.Object.PROPERTY_DATE_MODIFIED:
                 column = MtpObjects.ObjectColumns.DATE_MODIFIED;
                 break;
-            case MTP_PROPERTY_PARENT_OBJECT:
+            case Mtp.Object.PROPERTY_PARENT_OBJECT:
                 column = MtpObjects.ObjectColumns.PARENT;
                 break;
+            case Mtp.Object.PROPERTY_PERSISTENT_UID:
+                // PUID is concatenation of storageID and object handle
+                long puid = mStorageID;
+                puid <<= 32;
+                puid += handle;
+                outIntValue[0] = puid;
+                return MTP_RESPONSE_OK;
             default:
                 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
         }
@@ -305,7 +308,7 @@
                     String value = c.getString(1);
                     int start = 0;
 
-                    if (property == MTP_PROPERTY_OBJECT_FILE_NAME) {
+                    if (property == Mtp.Object.PROPERTY_OBJECT_FILE_NAME) {
                         // extract name from full path
                         int lastSlash = value.lastIndexOf('/');
                         if (lastSlash >= 0) {
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index bf83172..4ef3a9f 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -29,6 +29,7 @@
 
 #include "MtpDatabase.h"
 #include "MtpDataPacket.h"
+#include "MtpProperty.h"
 #include "MtpUtils.h"
 #include "mtp.h"
 
@@ -45,6 +46,7 @@
 static jmethodID method_getSupportedObjectProperties;
 static jmethodID method_getSupportedDeviceProperties;
 static jmethodID method_getObjectProperty;
+static jmethodID method_setObjectProperty;
 static jmethodID method_getObjectInfo;
 static jmethodID method_getObjectFilePath;
 static jmethodID method_deleteFile;
@@ -98,10 +100,22 @@
     virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format);
     virtual MtpDevicePropertyList*  getSupportedDeviceProperties();
 
-    virtual MtpResponseCode         getObjectProperty(MtpObjectHandle handle,
+    virtual MtpResponseCode         getObjectPropertyValue(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet);
 
+    virtual MtpResponseCode         setObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         getDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         setDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet);
+
+    virtual MtpResponseCode         resetDeviceProperty(MtpDeviceProperty property);
+
     virtual MtpResponseCode         getObjectInfo(MtpObjectHandle handle,
                                             MtpDataPacket& packet);
 
@@ -116,6 +130,11 @@
 
     virtual MtpResponseCode         setObjectReferences(MtpObjectHandle handle,
                                             MtpObjectHandleList* references);
+
+    virtual MtpProperty*            getObjectPropertyDesc(MtpObjectProperty property,
+                                            MtpObjectFormat format);
+
+    virtual MtpProperty*            getDevicePropertyDesc(MtpDeviceProperty property);
 };
 
 // ----------------------------------------------------------------------------
@@ -292,7 +311,7 @@
     return list;
 }
 
-MtpResponseCode MyMtpDatabase::getObjectProperty(MtpObjectHandle handle,
+MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet) {
     int         type;
@@ -310,6 +329,15 @@
     jlong longValue = longValues[0];
     env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
 
+    // special case MTP_PROPERTY_DATE_MODIFIED, which is a string to MTP
+    // but stored internally as a uint64
+    if (property == MTP_PROPERTY_DATE_MODIFIED) {
+        char    date[20];
+        formatDateTime(longValue, date, sizeof(date));
+        packet.putString(date);
+        return MTP_RESPONSE_OK;
+    }
+
     switch (type) {
         case MTP_TYPE_INT8:
             packet.putInt8(longValue);
@@ -335,6 +363,12 @@
         case MTP_TYPE_UINT64:
             packet.putUInt64(longValue);
             break;
+        case MTP_TYPE_INT128:
+            packet.putInt128(longValue);
+            break;
+        case MTP_TYPE_UINT128:
+            packet.putInt128(longValue);
+            break;
         case MTP_TYPE_STR:
         {
             jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
@@ -351,6 +385,26 @@
     return MTP_RESPONSE_OK;
 }
 
+MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet) {
+    return -1;
+}
+
+MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet) {
+    return -1;
+}
+
+MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet) {
+    return -1;
+}
+
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+    return -1;
+}
+
 MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
                                             MtpDataPacket& packet) {
     char    date[20];
@@ -372,9 +426,10 @@
     uint64_t modified = longValues[1];
     env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
 
-    int associationType = (format == MTP_FORMAT_ASSOCIATION ?
-                            MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
-                            MTP_ASSOCIATION_TYPE_UNDEFINED);
+//    int associationType = (format == MTP_FORMAT_ASSOCIATION ?
+//                            MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
+//                            MTP_ASSOCIATION_TYPE_UNDEFINED);
+    int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
 
     packet.putUInt32(storageID);
     packet.putUInt16(format);
@@ -497,6 +552,37 @@
     return result;
 }
 
+MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
+                                            MtpObjectFormat format) {
+    MtpProperty* result = NULL;
+    switch (property) {
+        case MTP_PROPERTY_OBJECT_FORMAT:
+        case MTP_PROPERTY_PROTECTION_STATUS:
+            result = new MtpProperty(property, MTP_TYPE_UINT16);
+            break;
+        case MTP_PROPERTY_STORAGE_ID:
+        case MTP_PROPERTY_PARENT_OBJECT:
+            result = new MtpProperty(property, MTP_TYPE_UINT32);
+            break;
+        case MTP_PROPERTY_OBJECT_SIZE:
+            result = new MtpProperty(property, MTP_TYPE_UINT64);
+            break;
+        case MTP_PROPERTY_PERSISTENT_UID:
+            result = new MtpProperty(property, MTP_TYPE_UINT128);
+            break;
+        case MTP_PROPERTY_OBJECT_FILE_NAME:
+        case MTP_PROPERTY_DATE_MODIFIED:
+            result = new MtpProperty(property, MTP_TYPE_STR);
+            break;
+    }
+
+    return result;
+}
+
+MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
+    return NULL;
+}
+
 #endif // HAVE_ANDROID_OS
 
 // ----------------------------------------------------------------------------
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 798271e..d856eb4 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -17,7 +17,7 @@
 
 #define LOG_TAG "Bundle"
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <cutils/log.h>
 #include <assert.h>
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 2043e44..03f1409 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -17,7 +17,7 @@
 
 #define LOG_TAG "Reverb"
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 
 #include <cutils/log.h>
 #include <assert.h>
@@ -61,42 +61,81 @@
 /* Preset definitions                                                               */
 /*                                                                                  */
 /************************************************************************************/
-LVM_UINT16 RevPreset_Level[]    = {  32,   32,   32,   32,   32,    32,   32,   32,   32,   32};
-LVM_UINT16 RevPreset_LPF[]      = {1298, 1000, 5012, 3542, 3400, 23999, 2536, 1000, 1000, 1000};
-LVM_UINT16 RevPreset_HPF[]      = {  50,   50,   50,   50,   50,    50,   50,   50,   50,   50};
-LVM_UINT16 RevPreset_T60[]      = {1490,  500, 2310, 4230, 3920,  2910, 7000, 1490, 1490,  170};
-LVM_UINT16 RevPreset_Density[]  = { 100,  100,  100,  100,  100,   100,  100,  100,  100,  100};
-LVM_UINT16 RevPreset_Damping[]  = {  54,   10,   64,   59,   70,   100,   33,   54,   21,   10};
-LVM_UINT16 RevPreset_RoomSize[] = { 100,  100,  100,  100,  100,   100,  100,  100,  100,  100};
 
-/************************************************************************************/
-/*                                                                                  */
-/* Preset definitions                                                               */
-/*                                                                                  */
-/************************************************************************************/
-#define REV_PRESET_BATHROOM         0
-#define REV_PRESET_LIVINGROOM       1
-#define REV_PRESET_STONEROOM        2
-#define REV_PRESET_AUDITORIUM       3
-#define REV_PRESET_CONCERTHALL      4
-#define REV_PRESET_CAVE             5
-#define REV_PRESET_ARENA            6
-#define REV_PRESET_FOREST           7
-#define REV_PRESET_MOUNTAINS        8
-#define REV_PRESET_PADDEDCELL       9
+const static t_reverb_settings sReverbPresets[] = {
+        // REVERB_PRESET_NONE: values are unused
+        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+        // REVERB_PRESET_SMALLROOM
+        {-1000, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
+        // REVERB_PRESET_MEDIUMROOM
+        {-1000, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
+        // REVERB_PRESET_LARGEROOM
+        {-1000, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
+        // REVERB_PRESET_MEDIUMHALL
+        {-1000, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
+        // REVERB_PRESET_LARGEHALL
+        {-1000, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
+        // REVERB_PRESET_PLATE
+        {-1000, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
+};
 
-// NXP SW Reverb UUID
-const effect_descriptor_t gReverbDescriptor = {
+
+// NXP SW auxiliary environmental reverb
+const effect_descriptor_t gAuxEnvReverbDescriptor = {
         { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e } },
         { 0x4a387fc0, 0x8ab3, 0x11df, 0x8bad, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
         EFFECT_API_VERSION,
-        (EFFECT_FLAG_TYPE_AUXILIARY | EFFECT_FLAG_INSERT_LAST),
+        EFFECT_FLAG_TYPE_AUXILIARY,
         0, // TODO
         1,
-        "Reverb",
+        "Auxiliary Environmental Reverb",
         "NXP Software Ltd.",
 };
 
+// NXP SW insert environmental reverb
+static const effect_descriptor_t gInsertEnvReverbDescriptor = {
+        {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+        {0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        0, // TODO
+        1,
+        "Insert Environmental Reverb",
+        "NXP Software Ltd.",
+};
+
+// NXP SW auxiliary preset reverb
+static const effect_descriptor_t gAuxPresetReverbDescriptor = {
+        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0xf29a1400, 0xa3bb, 0x11df, 0x8ddc, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_AUXILIARY,
+        0, // TODO
+        1,
+        "Auxiliary Preset Reverb",
+        "NXP Software Ltd.",
+};
+
+// NXP SW insert preset reverb
+static const effect_descriptor_t gInsertPresetReverbDescriptor = {
+        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        0, // TODO
+        1,
+        "Insert Preset Reverb",
+        "NXP Software Ltd.",
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+        &gAuxEnvReverbDescriptor,
+        &gInsertEnvReverbDescriptor,
+        &gAuxPresetReverbDescriptor,
+        &gInsertPresetReverbDescriptor
+};
+
 struct ReverbContext{
     const struct effect_interface_s *itfe;
     effect_config_t                 config;
@@ -114,8 +153,14 @@
     FILE                            *PcmOutPtr;
     #endif
     LVM_Fs_en                       SampleRate;
+    bool                            auxiliary;
+    bool                            preset;
+    uint16_t                        curPreset;
+    uint16_t                        nextPreset;
 };
 
+#define REVERB_DEFAULT_PRESET REVERB_PRESET_MEDIUMROOM
+
 //--- local function prototypes
 int  Reverb_init            (ReverbContext *pContext);
 void Reverb_free            (ReverbContext *pContext);
@@ -125,11 +170,12 @@
                              void          *pParam,
                              size_t        *pValueSize,
                              void          *pValue);
+int Reverb_LoadPreset       (ReverbContext   *pContext);
 
 /* Effect Library Interface Implementation */
 extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
     LOGV("\n\tEffectQueryNumberEffects start");
-    *pNumEffects = 1;
+    *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
     LOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
     LOGV("\tEffectQueryNumberEffects end\n");
     return 0;
@@ -142,11 +188,11 @@
         LOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
         return -EINVAL;
     }
-    if (index > 0){
+    if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
         LOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
         return -ENOENT;
     }
-    memcpy(pDescriptor, &gReverbDescriptor, sizeof(effect_descriptor_t));
+    memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t));
     LOGV("\tEffectQueryEffect end\n");
     return 0;
 }     /* end EffectQueryEffect */
@@ -157,6 +203,8 @@
                             effect_interface_t  *pInterface){
     int ret;
     int i;
+    int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+    const effect_descriptor_t *desc;
 
     LOGV("\t\nEffectCreate start");
 
@@ -165,9 +213,16 @@
         return -EINVAL;
     }
 
-    if (memcmp(uuid, &gReverbDescriptor.uuid, sizeof(effect_uuid_t)) != 0){
-        LOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
-        return -EINVAL;
+    for (i = 0; i < length; i++) {
+        desc = gDescriptors[i];
+        if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
+                == 0) {
+            break;
+        }
+    }
+
+    if (i == length) {
+        return -ENOENT;
     }
 
     ReverbContext *pContext = new ReverbContext;
@@ -175,6 +230,19 @@
     pContext->itfe      = &gReverbInterface;
     pContext->hInstance = NULL;
 
+    pContext->auxiliary = false;
+    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY){
+        pContext->auxiliary = true;
+    }
+
+    pContext->preset = false;
+    if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+        pContext->preset = true;
+        // force reloading preset at first call to process()
+        pContext->curPreset = REVERB_PRESET_LAST + 1;
+        pContext->nextPreset = REVERB_DEFAULT_PRESET;
+    }
+
     LOGV("\tEffectCreate - Calling Reverb_init");
     ret = Reverb_init(pContext);
 
@@ -288,6 +356,14 @@
 
    return;
 }
+
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
 //----------------------------------------------------------------------------
 // process()
 //----------------------------------------------------------------------------
@@ -344,6 +420,9 @@
     fflush(pContext->PcmInPtr);
     #endif
 
+    if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
+        Reverb_LoadPreset(pContext);
+    }
     // Convert to Input 32 bits
     for(int i=0; i<frameCount*samplesPerFrame; i++){
         InFrames32[i] = (LVM_INT32)pIn[i]<<8;
@@ -359,18 +438,28 @@
     //frameCount, pContext->config.inputCfg.channels, CHANNEL_MONO,
     //pContext->config.outputCfg.channels, CHANNEL_STEREO);
 
+    if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
+        memset(OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2);
+    } else {
     /* Process the samples */
     LvmStatus = LVREV_Process(pContext->hInstance,      /* Instance handle */
                               InFrames32,               /* Input buffer */
                               OutFrames32,              /* Output buffer */
                               frameCount);              /* Number of samples to read */
+    }
+
+    if (!pContext->auxiliary) {
+        for (int i=0; i<frameCount*2; i++){
+            OutFrames32[i] += InFrames32[i];
+        }
+    }
 
     LVM_ERROR_CHECK(LvmStatus, "LVREV_Process", "process")
     if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
 
     // Convert to 16 bits
     for(int i=0; i<frameCount*2; i++){  // Always stereo
-        OutFrames16[i] = (LVM_INT16)(OutFrames32[i]>>8);
+        OutFrames16[i] = clamp16(OutFrames32[i]>>8);
     }
 
     #ifdef LVM_PCM
@@ -382,7 +471,7 @@
     if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
         //LOGV("\tBuffer access is ACCUMULATE");
         for (int i=0; i<frameCount*2; i++){
-            pOut[i] +=  OutFrames16[i];
+            pOut[i] = clamp16((int32_t)pOut[i] + (int32_t)OutFrames16[i]);
         }
     }else{
         //LOGV("\tBuffer access is WRITE");
@@ -462,6 +551,8 @@
 
     CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
     CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+    CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == CHANNEL_MONO) ||
+              ((!pContext->auxiliary) && pConfig->inputCfg.channels == CHANNEL_STEREO));
     CHECK_ARG(pConfig->outputCfg.channels == CHANNEL_STEREO);
     CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
               || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
@@ -540,18 +631,8 @@
 
 int Reverb_init(ReverbContext *pContext){
     int status;
-    int channel_mode;
 
-    LOGV("\tReverb_init start %d", gReverbDescriptor.flags);
-
-    if((gReverbDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT){
-        LOGV("\tReverb_init EFFECT_FLAG_TYPE_INSERT");
-        channel_mode = CHANNEL_STEREO;
-    }
-    if((gReverbDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY ){
-        LOGV("\tReverb_init EFFECT_FLAG_TYPE_AUXILIARY");
-        channel_mode = CHANNEL_MONO;
-    }
+    LOGV("\tReverb_init start");
 
     CHECK_ARG(pContext != NULL);
 
@@ -560,7 +641,12 @@
     }
 
     pContext->config.inputCfg.accessMode                    = EFFECT_BUFFER_ACCESS_READ;
-    pContext->config.inputCfg.channels                      = channel_mode;
+    if (pContext->auxiliary) {
+        pContext->config.inputCfg.channels                  = CHANNEL_MONO;
+    } else {
+        pContext->config.inputCfg.channels                  = CHANNEL_STEREO;
+    }
+
     pContext->config.inputCfg.format                        = SAMPLE_FORMAT_PCM_S15;
     pContext->config.inputCfg.samplingRate                  = 44100;
     pContext->config.inputCfg.bufferProvider.getBuffer      = NULL;
@@ -653,11 +739,11 @@
     /* Reverb parameters */
     params.Level          = 0;
     params.LPF            = 23999;
-    params.HPF            = RevPreset_HPF[REV_PRESET_MOUNTAINS];
-    params.T60            = RevPreset_T60[REV_PRESET_MOUNTAINS];
-    params.Density        = RevPreset_Density[REV_PRESET_MOUNTAINS];
-    params.Damping        = RevPreset_Damping[REV_PRESET_MOUNTAINS];
-    params.RoomSize       = RevPreset_RoomSize[REV_PRESET_MOUNTAINS];
+    params.HPF            = 50;
+    params.T60            = 1490;
+    params.Density        = 100;
+    params.Damping        = 21;
+    params.RoomSize       = 100;
 
     /* Saved strength is used to return the exact strength that was used in the set to the get
      * because we map the original strength range of 0:1000 to 1:15, and this will avoid
@@ -1294,6 +1380,44 @@
 }
 
 //----------------------------------------------------------------------------
+// Reverb_LoadPreset()
+//----------------------------------------------------------------------------
+// Purpose:
+// Load a the next preset
+//
+// Inputs:
+//  pContext         - handle to instance data
+//
+// Outputs:
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+int Reverb_LoadPreset(ReverbContext   *pContext)
+{
+    //TODO: add reflections delay, level and reverb delay when early reflections are
+    // implemented
+    pContext->curPreset = pContext->nextPreset;
+
+    if (pContext->curPreset != REVERB_PRESET_NONE) {
+        const t_reverb_settings *preset = &sReverbPresets[pContext->curPreset];
+        ReverbSetRoomLevel(pContext, preset->roomLevel);
+        ReverbSetRoomHfLevel(pContext, preset->roomHFLevel);
+        ReverbSetDecayTime(pContext, preset->decayTime);
+        ReverbSetDecayHfRatio(pContext, preset->decayHFRatio);
+        //reflectionsLevel
+        //reflectionsDelay
+        ReverbSetReverbLevel(pContext, preset->reverbLevel);
+        // reverbDelay
+        ReverbSetDiffusion(pContext, preset->diffusion);
+        ReverbSetDensity(pContext, preset->density);
+    }
+
+    return 0;
+}
+
+
+//----------------------------------------------------------------------------
 // Reverb_getParameter()
 //----------------------------------------------------------------------------
 // Purpose:
@@ -1325,6 +1449,15 @@
     t_reverb_settings *pProperties;
 
     //LOGV("\tReverb_getParameter start");
+    if (pContext->preset) {
+        if (param != REVERB_PARAM_PRESET || *pValueSize < sizeof(uint16_t)) {
+            return -EINVAL;
+        }
+
+        *(uint16_t *)pValue = pContext->nextPreset;
+        LOGV("get REVERB_PARAM_PRESET, preset %d", pContext->nextPreset);
+        return 0;
+    }
 
     switch (param){
         case REVERB_PARAM_ROOM_LEVEL:
@@ -1531,6 +1664,18 @@
     int32_t param = *pParamTemp++;
 
     //LOGV("\tReverb_setParameter start");
+    if (pContext->preset) {
+        if (param != REVERB_PARAM_PRESET) {
+            return -EINVAL;
+        }
+
+        uint16_t preset = *(uint16_t *)pValue;
+        LOGV("set REVERB_PARAM_PRESET, preset %d", preset);
+        if (preset > REVERB_PRESET_LAST) {
+            return -EINVAL;
+        }
+        pContext->nextPreset = preset;
+    }
 
     switch (param){
         case REVERB_PARAM_PROPERTIES:
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e167afa..1ccfa03 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -461,27 +461,34 @@
         return;
     }
 
+    bool eos;
+    size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
+
     size_t lowWatermark = 400000;
     size_t highWatermark = 1000000;
 
-    off_t size;
-    if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
-        int64_t bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
+    if (eos) {
+        notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+    } else {
+        off_t size;
+        if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
+            int64_t bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
 
-        size_t cachedSize = mCachedSource->cachedSize();
-        int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
+            size_t cachedSize = mCachedSource->cachedSize();
+            int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
 
-        double percentage = (double)cachedDurationUs / mDurationUs;
+            int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+            if (percentage > 100) {
+                percentage = 100;
+            }
 
-        notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
+            notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
 
-        lowWatermark = 2 * bitrate / 8;  // 2 secs
-        highWatermark = 10 * bitrate / 8;  // 10 secs
+            lowWatermark = 2 * bitrate / 8;  // 2 secs
+            highWatermark = 10 * bitrate / 8;  // 10 secs
+        }
     }
 
-    bool eos;
-    size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
-
     if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
         LOGI("cache is running low (< %d) , pausing.", lowWatermark);
         mFlags |= CACHE_UNDERRUN;
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index ca0c68c..da340f7 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -142,11 +142,22 @@
     mSize = size;
 
     if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
+        free(mData);
+        mData = NULL;
+
         return false;
     }
 
-    if (header.flags & 0x80) {
+    if (header.version_major == 4) {
+        if (!removeUnsynchronizationV2_4()) {
+            free(mData);
+            mData = NULL;
+
+            return false;
+        }
+    } else if (header.flags & 0x80) {
         LOGV("removing unsynchronization");
+
         removeUnsynchronization();
     }
 
@@ -243,6 +254,74 @@
     }
 }
 
+static void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
+    for (size_t i = 0; i < 4; ++i) {
+        dst[3 - i] = (x & 0x7f);
+        x >>= 7;
+    }
+}
+
+bool ID3::removeUnsynchronizationV2_4() {
+    size_t oldSize = mSize;
+
+    size_t offset = 0;
+    while (offset + 10 <= mSize) {
+        if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
+            break;
+        }
+
+        size_t dataSize;
+        if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
+            return false;
+        }
+
+        if (offset + dataSize + 10 > mSize) {
+            return false;
+        }
+
+        uint16_t flags = U16_AT(&mData[offset + 8]);
+        uint16_t prevFlags = flags;
+
+        if (flags & 1) {
+            // Strip data length indicator
+
+            memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
+            mSize -= 4;
+            dataSize -= 4;
+
+            flags &= ~1;
+        }
+
+        if (flags & 2) {
+            // Unsynchronization added.
+
+            for (size_t i = 0; i + 1 < dataSize; ++i) {
+                if (mData[offset + 10 + i] == 0xff
+                        && mData[offset + 11 + i] == 0x00) {
+                    memmove(&mData[offset + 11 + i], &mData[offset + 12 + i],
+                            mSize - offset - 12 - i);
+                    --mSize;
+                    --dataSize;
+                }
+            }
+
+            flags &= ~2;
+        }
+
+        if (flags != prevFlags) {
+            WriteSyncsafeInteger(&mData[offset + 4], dataSize);
+            mData[offset + 8] = flags >> 8;
+            mData[offset + 9] = flags & 0xff;
+        }
+
+        offset += 10 + dataSize;
+    }
+
+    memset(&mData[mSize], 0, oldSize - mSize);
+
+    return true;
+}
+
 ID3::Iterator::Iterator(const ID3 &parent, const char *id)
     : mParent(parent),
       mID(NULL),
@@ -529,10 +608,11 @@
 
             uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
 
-            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000e))
+            if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
                 || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
-                // Compression, Encryption or per-Frame unsynchronization
-                // are not supported at this time.
+                // Compression or encryption are not supported at this time.
+                // Per-frame unsynchronization and data-length indicator
+                // have already been taken care of.
 
                 LOGV("Skipping unsupported frame (compression, encryption "
                      "or per-frame unsynchronization flagged");
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index c6b1a8b..7ddbb41 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -80,6 +80,7 @@
     bool parseV1(const sp<DataSource> &source);
     bool parseV2(const sp<DataSource> &source);
     void removeUnsynchronization();
+    bool removeUnsynchronizationV2_4();
 
     static bool ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x);
 
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 27dc796..ec78ff0 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -242,6 +242,16 @@
     putUInt32(value[3]);
 }
 
+void MtpDataPacket::putInt128(int64_t value) {
+    putInt64(value);
+    putInt64(value < 0 ? -1 : 0);
+}
+
+void MtpDataPacket::putUInt128(uint64_t value) {
+    putUInt64(value);
+    putUInt64(0);
+}
+
 void MtpDataPacket::putAInt8(const int8_t* values, int count) {
     putUInt32(count);
     for (int i = 0; i < count; i++)
@@ -363,7 +373,7 @@
 int MtpDataPacket::write(int fd) {
     MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
     MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
-
+    dump();
     // send header separately from data
     int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
     if (ret == MTP_CONTAINER_HEADER_SIZE)
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 1467aab..fab6a07 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -69,6 +69,8 @@
     void                putUInt64(uint64_t value);
     void                putInt128(const int128_t& value);
     void                putUInt128(const uint128_t& value);
+    void                putInt128(int64_t value);
+    void                putUInt128(uint64_t value);
 
     void                putAInt8(const int8_t* values, int count);
     void                putAUInt8(const uint8_t* values, int count);
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index 17823df..899b34a 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -22,6 +22,7 @@
 namespace android {
 
 class MtpDataPacket;
+class MtpProperty;
 
 class MtpDatabase {
 public:
@@ -58,10 +59,22 @@
     virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format) = 0;
     virtual MtpDevicePropertyList*  getSupportedDeviceProperties() = 0;
 
-    virtual MtpResponseCode         getObjectProperty(MtpObjectHandle handle,
+    virtual MtpResponseCode         getObjectPropertyValue(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet) = 0;
 
+    virtual MtpResponseCode         setObjectPropertyValue(MtpObjectHandle handle,
+                                            MtpObjectProperty property,
+                                            MtpDataPacket& packet) = 0;
+
+    virtual MtpResponseCode         getDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet) = 0;
+
+    virtual MtpResponseCode         setDevicePropertyValue(MtpDeviceProperty property,
+                                            MtpDataPacket& packet) = 0;
+
+    virtual MtpResponseCode         resetDeviceProperty(MtpDeviceProperty property) = 0;
+
     virtual MtpResponseCode         getObjectInfo(MtpObjectHandle handle,
                                             MtpDataPacket& packet) = 0;
 
@@ -76,6 +89,10 @@
     virtual MtpResponseCode         setObjectReferences(MtpObjectHandle handle,
                                             MtpObjectHandleList* references) = 0;
 
+    virtual MtpProperty*            getObjectPropertyDesc(MtpObjectProperty property,
+                                            MtpObjectFormat format) = 0;
+
+    virtual MtpProperty*            getDevicePropertyDesc(MtpDeviceProperty property) = 0;
 };
 
 }; // namespace android
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 30abfb8..1e64e4f 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -56,17 +56,17 @@
 //    MTP_OPERATION_SET_OBJECT_PROTECTION,
 //    MTP_OPERATION_POWER_DOWN,
 //    MTP_OPERATION_GET_DEVICE_PROP_DESC,
-//    MTP_OPERATION_GET_DEVICE_PROP_VALUE,
-//    MTP_OPERATION_SET_DEVICE_PROP_VALUE,
-//    MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
+    MTP_OPERATION_GET_DEVICE_PROP_VALUE,
+    MTP_OPERATION_SET_DEVICE_PROP_VALUE,
+    MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
 //    MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
 //    MTP_OPERATION_MOVE_OBJECT,
 //    MTP_OPERATION_COPY_OBJECT,
 //    MTP_OPERATION_GET_PARTIAL_OBJECT,
 //    MTP_OPERATION_INITIATE_OPEN_CAPTURE,
     MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
-//    MTP_OPERATION_GET_OBJECT_PROP_DESC,
-    MTP_OPERATION_GET_OBJECT_PROP_VALUE,
+    MTP_OPERATION_GET_OBJECT_PROP_DESC,
+//    MTP_OPERATION_GET_OBJECT_PROP_VALUE,
 //    MTP_OPERATION_SET_OBJECT_PROP_VALUE,
     MTP_OPERATION_GET_OBJECT_REFERENCES,
     MTP_OPERATION_SET_OBJECT_REFERENCES,
@@ -91,7 +91,6 @@
         mSendObjectFormat(0),
         mSendObjectFileSize(0)
 {
-    initObjectProperties();
 }
 
 MtpServer::~MtpServer() {
@@ -136,7 +135,9 @@
 
         // FIXME need to generalize this
         bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO
-                    || operation == MTP_OPERATION_SET_OBJECT_REFERENCES);
+                    || operation == MTP_OPERATION_SET_OBJECT_REFERENCES
+                    || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE
+                    || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE);
         if (dataIn) {
             int ret = mData.read(fd);
             if (ret < 0) {
@@ -158,7 +159,6 @@
                 mData.setOperationCode(operation);
                 mData.setTransactionID(transaction);
                 LOGV("sending data:");
-                mData.dump();
                 ret = mData.write(fd);
                 if (ret < 0) {
                     LOGE("request write returned %d, errno: %d", ret, errno);
@@ -187,24 +187,6 @@
     }
 }
 
-MtpProperty* MtpServer::getObjectProperty(MtpPropertyCode propCode) {
-    for (int i = 0; i < mObjectProperties.size(); i++) {
-        MtpProperty* property = mObjectProperties[i];
-        if (property->getPropertyCode() == propCode)
-            return property;
-    }
-    return NULL;
-}
-
-MtpProperty* MtpServer::getDeviceProperty(MtpPropertyCode propCode) {
-    for (int i = 0; i < mDeviceProperties.size(); i++) {
-        MtpProperty* property = mDeviceProperties[i];
-        if (property->getPropertyCode() == propCode)
-            return property;
-    }
-    return NULL;
-}
-
 void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
     if (mSessionOpen) {
         LOGD("sendObjectAdded %d\n", handle);
@@ -227,14 +209,6 @@
     }
 }
 
-void MtpServer::initObjectProperties() {
-    mObjectProperties.push(new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32));
-    mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16));
-    mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64));
-    mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR));
-    mObjectProperties.push(new MtpProperty(MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32));
-}
-
 bool MtpServer::handleRequest() {
     MtpOperationCode operation = mRequest.getOperationCode();
     MtpResponseCode response;
@@ -281,6 +255,18 @@
         case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
             response = doGetObjectPropValue();
             break;
+        case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
+            response = doSetObjectPropValue();
+            break;
+        case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
+            response = doGetDevicePropValue();
+            break;
+        case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
+            response = doSetDevicePropValue();
+            break;
+        case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
+            response = doResetDevicePropValue();
+            break;
         case MTP_OPERATION_GET_OBJECT_INFO:
             response = doGetObjectInfo();
             break;
@@ -456,13 +442,15 @@
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
     MtpStorageID handle = mRequest.getParameter(1);
+
+    // FIXME - check for invalid object handle
     MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
-    if (!handles) {
+    if (handles) {
+        mData.putAUInt32(handles);
+        delete handles;
+    } else {
         mData.putEmptyArray();
-        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
     }
-    mData.putAUInt32(handles);
-    delete handles;
     return MTP_RESPONSE_OK;
 }
 
@@ -479,8 +467,43 @@
 MtpResponseCode MtpServer::doGetObjectPropValue() {
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectProperty property = mRequest.getParameter(2);
+    LOGD("GetObjectPropValue %d %s\n", handle,
+            MtpDebug::getObjectPropCodeName(property));
 
-    return mDatabase->getObjectProperty(handle, property, mData);
+    return mDatabase->getObjectPropertyValue(handle, property, mData);
+}
+
+MtpResponseCode MtpServer::doSetObjectPropValue() {
+    MtpObjectHandle handle = mRequest.getParameter(1);
+    MtpObjectProperty property = mRequest.getParameter(2);
+    LOGD("SetObjectPropValue %d %s\n", handle,
+            MtpDebug::getObjectPropCodeName(property));
+
+    return mDatabase->setObjectPropertyValue(handle, property, mData);
+}
+
+MtpResponseCode MtpServer::doGetDevicePropValue() {
+    MtpDeviceProperty property = mRequest.getParameter(1);
+    LOGD("GetDevicePropValue %s\n",
+            MtpDebug::getDevicePropCodeName(property));
+
+    return mDatabase->getDevicePropertyValue(property, mData);
+}
+
+MtpResponseCode MtpServer::doSetDevicePropValue() {
+    MtpDeviceProperty property = mRequest.getParameter(1);
+    LOGD("SetDevicePropValue %s\n",
+            MtpDebug::getDevicePropCodeName(property));
+
+    return mDatabase->setDevicePropertyValue(property, mData);
+}
+
+MtpResponseCode MtpServer::doResetDevicePropValue() {
+    MtpDeviceProperty property = mRequest.getParameter(1);
+    LOGD("ResetDevicePropValue %s\n",
+            MtpDebug::getDevicePropCodeName(property));
+
+    return mDatabase->resetDeviceProperty(property);
 }
 
 MtpResponseCode MtpServer::doGetObjectInfo() {
@@ -592,7 +615,7 @@
     }
 
     mResponse.setParameter(1, storageID);
-    mResponse.setParameter(2, (parent == 0 ? 0xFFFFFFFF: parent));
+    mResponse.setParameter(2, parent);
     mResponse.setParameter(3, handle);
 
     return MTP_RESPONSE_OK;
@@ -677,11 +700,24 @@
 MtpResponseCode MtpServer::doGetObjectPropDesc() {
     MtpObjectProperty propCode = mRequest.getParameter(1);
     MtpObjectFormat format = mRequest.getParameter(2);
-    MtpProperty* property = getObjectProperty(propCode);
+    LOGD("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
+                                        MtpDebug::getFormatCodeName(format));
+    MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
     if (!property)
         return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
-
     property->write(mData);
+    delete property;
+    return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetDevicePropDesc() {
+    MtpDeviceProperty propCode = mRequest.getParameter(1);
+    LOGD("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
+    MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
+    if (!property)
+        return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+    property->write(mData);
+    delete property;
     return MTP_RESPONSE_OK;
 }
 
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 19ccf24..68a6564 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -28,7 +28,6 @@
 namespace android {
 
 class MtpDatabase;
-class MtpProperty;
 class MtpStorage;
 
 class MtpServer {
@@ -57,9 +56,6 @@
 
     MtpStorageList      mStorages;
 
-    MtpPropertyList     mObjectProperties;
-    MtpPropertyList     mDeviceProperties;
-
     // handle for new object, set by SendObjectInfo and used by SendObject
     MtpObjectHandle     mSendObjectHandle;
     MtpObjectFormat     mSendObjectFormat;
@@ -76,15 +72,10 @@
     MtpStorage*         getStorage(MtpStorageID id);
     void                run();
 
-    MtpProperty*        getObjectProperty(MtpPropertyCode propCode);
-    MtpProperty*        getDeviceProperty(MtpPropertyCode propCode);
-
     void                sendObjectAdded(MtpObjectHandle handle);
     void                sendObjectRemoved(MtpObjectHandle handle);
 
 private:
-    void                initObjectProperties();
-
     bool                handleRequest();
 
     MtpResponseCode     doGetDeviceInfo();
@@ -98,12 +89,17 @@
     MtpResponseCode     doGetObjectReferences();
     MtpResponseCode     doSetObjectReferences();
     MtpResponseCode     doGetObjectPropValue();
+    MtpResponseCode     doSetObjectPropValue();
+    MtpResponseCode     doGetDevicePropValue();
+    MtpResponseCode     doSetDevicePropValue();
+    MtpResponseCode     doResetDevicePropValue();
     MtpResponseCode     doGetObjectInfo();
     MtpResponseCode     doGetObject();
     MtpResponseCode     doSendObjectInfo();
     MtpResponseCode     doSendObject();
     MtpResponseCode     doDeleteObject();
     MtpResponseCode     doGetObjectPropDesc();
+    MtpResponseCode     doGetDevicePropDesc();
 };
 
 }; // namespace android
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 56159b5..aa72616 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -610,8 +610,8 @@
      * All currently bound service connections.  Keys are the IBinder of
      * the client's IServiceConnection.
      */
-    final HashMap<IBinder, ConnectionRecord> mServiceConnections
-            = new HashMap<IBinder, ConnectionRecord>();
+    final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
+            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
 
     /**
      * List of services that we have been asked to start,
@@ -7404,12 +7404,14 @@
             if (mServiceConnections.size() > 0) {
                 if (needSep) pw.println(" ");
                 pw.println("  Connection bindings to services:");
-                Iterator<ConnectionRecord> it
+                Iterator<ArrayList<ConnectionRecord>> it
                         = mServiceConnections.values().iterator();
                 while (it.hasNext()) {
-                    ConnectionRecord r = it.next();
-                    pw.print("  * "); pw.println(r);
-                    r.dump(pw, "    ");
+                    ArrayList<ConnectionRecord> r = it.next();
+                    for (int i=0; i<r.size(); i++) {
+                        pw.print("  * "); pw.println(r.get(i));
+                        r.get(i).dump(pw, "    ");
+                    }
                 }
                 needSep = true;
             }
@@ -7687,18 +7689,21 @@
                 while (it.hasNext()) {
                     ServiceRecord r = it.next();
                     if (r.connections.size() > 0) {
-                        Iterator<ConnectionRecord> jt
+                        Iterator<ArrayList<ConnectionRecord>> jt
                                 = r.connections.values().iterator();
                         while (jt.hasNext()) {
-                            ConnectionRecord c = jt.next();
-                            if (c.binding.client != app) {
-                                try {
-                                    //c.conn.connected(r.className, null);
-                                } catch (Exception e) {
-                                    // todo: this should be asynchronous!
-                                    Slog.w(TAG, "Exception thrown disconnected servce "
-                                          + r.shortName
-                                          + " from app " + app.processName, e);
+                            ArrayList<ConnectionRecord> cl = jt.next();
+                            for (int i=0; i<cl.size(); i++) {
+                                ConnectionRecord c = cl.get(i);
+                                if (c.binding.client != app) {
+                                    try {
+                                        //c.conn.connected(r.className, null);
+                                    } catch (Exception e) {
+                                        // todo: this should be asynchronous!
+                                        Slog.w(TAG, "Exception thrown disconnected servce "
+                                              + r.shortName
+                                              + " from app " + app.processName, e);
+                                    }
                                 }
                             }
                         }
@@ -7728,7 +7733,9 @@
                 }
                 sr.app = null;
                 sr.executeNesting = 0;
-                mStoppingServices.remove(sr);
+                if (mStoppingServices.remove(sr)) {
+                    if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+                }
                 
                 boolean hasClients = sr.bindings.size() > 0;
                 if (hasClients) {
@@ -7781,6 +7788,7 @@
             ServiceRecord sr = mStoppingServices.get(i);
             if (sr.app == app) {
                 mStoppingServices.remove(i);
+                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
             }
         }
         
@@ -8044,11 +8052,15 @@
         if (r.app != null && r.app.persistent) {
             info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
         }
-        for (ConnectionRecord conn : r.connections.values()) {
-            if (conn.clientLabel != 0) {
-                info.clientPackage = conn.binding.client.info.packageName;
-                info.clientLabel = conn.clientLabel;
-                break;
+
+        for (ArrayList<ConnectionRecord> connl : r.connections.values()) {
+            for (int i=0; i<connl.size(); i++) {
+                ConnectionRecord conn = connl.get(i);
+                if (conn.clientLabel != 0) {
+                    info.clientPackage = conn.binding.client.info.packageName;
+                    info.clientLabel = conn.clientLabel;
+                    return info;
+                }
             }
         }
         return info;
@@ -8083,9 +8095,11 @@
         synchronized (this) {
             ServiceRecord r = mServices.get(name);
             if (r != null) {
-                for (ConnectionRecord conn : r.connections.values()) {
-                    if (conn.clientIntent != null) {
-                        return conn.clientIntent;
+                for (ArrayList<ConnectionRecord> conn : r.connections.values()) {
+                    for (int i=0; i<conn.size(); i++) {
+                        if (conn.get(i).clientIntent != null) {
+                            return conn.get(i).clientIntent;
+                        }
                     }
                 }
             }
@@ -8262,8 +8276,8 @@
         while (r.pendingStarts.size() > 0) {
             try {
                 ServiceRecord.StartItem si = r.pendingStarts.remove(0);
-                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: "
-                        + r.name + " " + r.intent + " args=" + si.intent);
+                if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
+                        + r + " " + r.intent + " args=" + si.intent);
                 if (si.intent == null) {
                     // If somehow we got a dummy start at the front, then
                     // just drop it here.
@@ -8276,6 +8290,7 @@
                     grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
                             r.packageName, si.intent, si);
                 }
+                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
                 bumpServiceExecutingLocked(r);
                 if (!oomAdjusted) {
                     oomAdjusted = true;
@@ -8292,6 +8307,7 @@
             } catch (RemoteException e) {
                 // Remote process gone...  we'll let the normal cleanup take
                 // care of this.
+                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
                 break;
             } catch (Exception e) {
                 Slog.w(TAG, "Unexpected exception", e);
@@ -8308,9 +8324,9 @@
         }
         if ((!i.requested || rebind) && i.apps.size() > 0) {
             try {
+                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
+                        + " in " + i + ": shouldUnbind=" + i.hasBound);
                 bumpServiceExecutingLocked(r);
-                if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i
-                        + ": shouldUnbind=" + i.hasBound);
                 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
                 if (!rebind) {
                     i.requested = true;
@@ -8318,6 +8334,7 @@
                 i.hasBound = true;
                 i.doRebind = false;
             } catch (RemoteException e) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
                 return false;
             }
         }
@@ -8344,13 +8361,12 @@
         r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
 
         app.services.add(r);
+        if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
         bumpServiceExecutingLocked(r);
         updateLruProcessLocked(app, true, true);
 
         boolean created = false;
         try {
-            if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: "
-                    + r.name + " " + r.intent);
             mStringBuilder.setLength(0);
             r.intent.getIntent().toShortString(mStringBuilder, false, true);
             EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
@@ -8510,8 +8526,7 @@
             return true;
         }
 
-        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name
-                + " " + r.intent);
+        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
 
         // We are now bringing the service up, so no longer in the
         // restarting state.
@@ -8562,27 +8577,30 @@
             if (!force) {
                 // XXX should probably keep a count of the number of auto-create
                 // connections directly in the service.
-                Iterator<ConnectionRecord> it = r.connections.values().iterator();
+                Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
                 while (it.hasNext()) {
-                    ConnectionRecord cr = it.next();
-                    if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
-                        return;
+                    ArrayList<ConnectionRecord> cr = it.next();
+                    for (int i=0; i<cr.size(); i++) {
+                        if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+                            return;
+                        }
                     }
                 }
             }
 
             // Report to all of the connections that the service is no longer
             // available.
-            Iterator<ConnectionRecord> it = r.connections.values().iterator();
+            Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
             while (it.hasNext()) {
-                ConnectionRecord c = it.next();
-                try {
-                    // todo: shouldn't be a synchronous call!
-                    c.conn.connected(r.name, null);
-                } catch (Exception e) {
-                    Slog.w(TAG, "Failure disconnecting service " + r.name +
-                          " to connection " + c.conn.asBinder() +
-                          " (in " + c.binding.client.processName + ")", e);
+                ArrayList<ConnectionRecord> c = it.next();
+                for (int i=0; i<c.size(); i++) {
+                    try {
+                        c.get(i).conn.connected(r.name, null);
+                    } catch (Exception e) {
+                        Slog.w(TAG, "Failure disconnecting service " + r.name +
+                              " to connection " + c.get(i).conn.asBinder() +
+                              " (in " + c.get(i).binding.client.processName + ")", e);
+                    }
                 }
             }
         }
@@ -8596,6 +8614,8 @@
                         + ": hasBound=" + ibr.hasBound);
                 if (r.app != null && r.app.thread != null && ibr.hasBound) {
                     try {
+                        if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
+                                + " for " + ibr);
                         bumpServiceExecutingLocked(r);
                         updateOomAdjLocked(r.app);
                         ibr.hasBound = false;
@@ -8610,15 +8630,13 @@
             }
         }
 
-        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name
-                 + " " + r.intent);
+        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
         EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,
                 System.identityHashCode(r), r.shortName,
                 (r.app != null) ? r.app.pid : -1);
 
         mServices.remove(r.name);
         mServicesByIntent.remove(r.intent);
-        if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName);
         r.totalRestartCount = 0;
         unscheduleServiceRestartLocked(r);
 
@@ -8627,8 +8645,7 @@
         for (int i=0; i<N; i++) {
             if (mPendingServices.get(i) == r) {
                 mPendingServices.remove(i);
-                if (DEBUG_SERVICE) Slog.v(
-                    TAG, "Removed pending service: " + r.shortName);
+                if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
                 i--;
                 N--;
             }
@@ -8650,8 +8667,11 @@
             r.app.services.remove(r);
             if (r.app.thread != null) {
                 try {
-                    if (DEBUG_SERVICE) Slog.v(TAG,
-                            "Stopping service: " + r.shortName);
+                    if (DEBUG_SERVICE) {
+                        RuntimeException here = new RuntimeException();
+                        here.fillInStackTrace();
+                        Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
+                    }
                     bumpServiceExecutingLocked(r);
                     mStoppingServices.add(r);
                     updateOomAdjLocked(r.app);
@@ -8664,11 +8684,11 @@
                 updateServiceForegroundLocked(r.app, false);
             } else {
                 if (DEBUG_SERVICE) Slog.v(
-                    TAG, "Removed service that has no process: " + r.shortName);
+                    TAG, "Removed service that has no process: " + r);
             }
         } else {
             if (DEBUG_SERVICE) Slog.v(
-                TAG, "Removed service that is not running: " + r.shortName);
+                TAG, "Removed service that is not running: " + r);
         }
     }
 
@@ -8703,8 +8723,7 @@
             int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
                     callingUid, r.packageName, service);
             if (unscheduleServiceRestartLocked(r)) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: "
-                        + r.shortName);
+                if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
             }
             r.startRequested = true;
             r.callStart = false;
@@ -8998,7 +9017,7 @@
 
             if (unscheduleServiceRestartLocked(s)) {
                 if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
-                        + s.shortName);
+                        + s);
             }
 
             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
@@ -9006,7 +9025,12 @@
                     connection, flags, clientLabel, clientIntent);
 
             IBinder binder = connection.asBinder();
-            s.connections.put(binder, c);
+            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+            if (clist == null) {
+                clist = new ArrayList<ConnectionRecord>();
+                s.connections.put(binder, clist);
+            }
+            clist.add(c);
             b.connections.add(c);
             if (activity != null) {
                 if (activity.connections == null) {
@@ -9015,7 +9039,12 @@
                 activity.connections.add(c);
             }
             b.client.connections.add(c);
-            mServiceConnections.put(binder, c);
+            clist = mServiceConnections.get(binder);
+            if (clist == null) {
+                clist = new ArrayList<ConnectionRecord>();
+                mServiceConnections.put(binder, clist);
+            }
+            clist.add(c);
 
             if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                 s.lastActivity = SystemClock.uptimeMillis();
@@ -9066,7 +9095,13 @@
         IBinder binder = c.conn.asBinder();
         AppBindRecord b = c.binding;
         ServiceRecord s = b.service;
-        s.connections.remove(binder);
+        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
+        if (clist != null) {
+            clist.remove(c);
+            if (clist.size() == 0) {
+                s.connections.remove(binder);
+            }
+        }
         b.connections.remove(c);
         if (c.activity != null && c.activity != skipAct) {
             if (c.activity.connections != null) {
@@ -9076,7 +9111,13 @@
         if (b.client != skipApp) {
             b.client.connections.remove(c);
         }
-        mServiceConnections.remove(binder);
+        clist = mServiceConnections.get(binder);
+        if (clist != null) {
+            clist.remove(c);
+            if (clist.size() == 0) {
+                mServiceConnections.remove(binder);
+            }
+        }
 
         if (b.connections.size() == 0) {
             b.intent.apps.remove(b.client);
@@ -9087,6 +9128,8 @@
         if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
                 && b.intent.hasBound) {
             try {
+                if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
+                        + " from " + b);
                 bumpServiceExecutingLocked(s);
                 updateOomAdjLocked(s.app);
                 b.intent.hasBound = false;
@@ -9109,8 +9152,8 @@
         synchronized (this) {
             IBinder binder = connection.asBinder();
             if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
-            ConnectionRecord r = mServiceConnections.get(binder);
-            if (r == null) {
+            ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
+            if (clist == null) {
                 Slog.w(TAG, "Unbind failed: could not find connection for "
                       + connection.asBinder());
                 return false;
@@ -9118,11 +9161,14 @@
 
             final long origId = Binder.clearCallingIdentity();
 
-            removeConnectionLocked(r, null, null);
+            while (clist.size() > 0) {
+                ConnectionRecord r = clist.get(0);
+                removeConnectionLocked(r, null, null);
 
-            if (r.binding.service.app != null) {
-                // This could have made the service less important.
-                updateOomAdjLocked(r.binding.service.app);
+                if (r.binding.service.app != null) {
+                    // This could have made the service less important.
+                    updateOomAdjLocked(r.binding.service.app);
+                }
             }
 
             Binder.restoreCallingIdentity(origId);
@@ -9145,7 +9191,7 @@
 
             final long origId = Binder.clearCallingIdentity();
 
-            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name
+            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
                     + " " + intent + ": " + service);
             if (r != null) {
                 Intent.FilterComparison filter
@@ -9156,26 +9202,29 @@
                     b.requested = true;
                     b.received = true;
                     if (r.connections.size() > 0) {
-                        Iterator<ConnectionRecord> it
+                        Iterator<ArrayList<ConnectionRecord>> it
                                 = r.connections.values().iterator();
                         while (it.hasNext()) {
-                            ConnectionRecord c = it.next();
-                            if (!filter.equals(c.binding.intent.intent)) {
-                                if (DEBUG_SERVICE) Slog.v(
-                                        TAG, "Not publishing to: " + c);
-                                if (DEBUG_SERVICE) Slog.v(
-                                        TAG, "Bound intent: " + c.binding.intent.intent);
-                                if (DEBUG_SERVICE) Slog.v(
-                                        TAG, "Published intent: " + intent);
-                                continue;
-                            }
-                            if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
-                            try {
-                                c.conn.connected(r.name, service);
-                            } catch (Exception e) {
-                                Slog.w(TAG, "Failure sending service " + r.name +
-                                      " to connection " + c.conn.asBinder() +
-                                      " (in " + c.binding.client.processName + ")", e);
+                            ArrayList<ConnectionRecord> clist = it.next();
+                            for (int i=0; i<clist.size(); i++) {
+                                ConnectionRecord c = clist.get(i);
+                                if (!filter.equals(c.binding.intent.intent)) {
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Not publishing to: " + c);
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Bound intent: " + c.binding.intent.intent);
+                                    if (DEBUG_SERVICE) Slog.v(
+                                            TAG, "Published intent: " + intent);
+                                    continue;
+                                }
+                                if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+                                try {
+                                    c.conn.connected(r.name, service);
+                                } catch (Exception e) {
+                                    Slog.w(TAG, "Failure sending service " + r.name +
+                                          " to connection " + c.conn.asBinder() +
+                                          " (in " + c.binding.client.processName + ")", e);
+                                }
                             }
                         }
                     }
@@ -9236,9 +9285,6 @@
             ServiceRecord r = (ServiceRecord)token;
             boolean inStopping = mStoppingServices.contains(token);
             if (r != null) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name
-                        + ": nesting=" + r.executeNesting
-                        + ", inStopping=" + inStopping);
                 if (r != token) {
                     Slog.w(TAG, "Done executing service " + r.name
                           + " with incorrect token: given " + token
@@ -9295,13 +9341,16 @@
                 serviceDoneExecutingLocked(r, inStopping);
                 Binder.restoreCallingIdentity(origId);
             } else {
-                Slog.w(TAG, "Done executing unknown service " + r.name
-                        + " with token " + token);
+                Slog.w(TAG, "Done executing unknown service from pid "
+                        + Binder.getCallingPid());
             }
         }
     }
 
     public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+        if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+                + ": nesting=" + r.executeNesting
+                + ", inStopping=" + inStopping + ", app=" + r.app);
         r.executeNesting--;
         if (r.executeNesting <= 0 && r.app != null) {
             r.app.executingServices.remove(r);
@@ -9309,6 +9358,7 @@
                 mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
             }
             if (inStopping) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
                 mStoppingServices.remove(r);
             }
             updateOomAdjLocked(r.app);
@@ -11099,61 +11149,64 @@
                 }
                 if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
                         || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
-                    Iterator<ConnectionRecord> kt
+                    Iterator<ArrayList<ConnectionRecord>> kt
                             = s.connections.values().iterator();
                     while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
-                        // XXX should compute this based on the max of
-                        // all connected clients.
-                        ConnectionRecord cr = kt.next();
-                        if (cr.binding.client == app) {
-                            // Binding to ourself is not interesting.
-                            continue;
-                        }
-                        if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
-                            ProcessRecord client = cr.binding.client;
-                            int myHiddenAdj = hiddenAdj;
-                            if (myHiddenAdj > client.hiddenAdj) {
-                                if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
-                                    myHiddenAdj = client.hiddenAdj;
-                                } else {
-                                    myHiddenAdj = VISIBLE_APP_ADJ;
+                        ArrayList<ConnectionRecord> clist = kt.next();
+                        for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) {
+                            // XXX should compute this based on the max of
+                            // all connected clients.
+                            ConnectionRecord cr = clist.get(i);
+                            if (cr.binding.client == app) {
+                                // Binding to ourself is not interesting.
+                                continue;
+                            }
+                            if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
+                                ProcessRecord client = cr.binding.client;
+                                int myHiddenAdj = hiddenAdj;
+                                if (myHiddenAdj > client.hiddenAdj) {
+                                    if (client.hiddenAdj >= VISIBLE_APP_ADJ) {
+                                        myHiddenAdj = client.hiddenAdj;
+                                    } else {
+                                        myHiddenAdj = VISIBLE_APP_ADJ;
+                                    }
+                                }
+                                int clientAdj = computeOomAdjLocked(
+                                    client, myHiddenAdj, TOP_APP, true);
+                                if (adj > clientAdj) {
+                                    adj = clientAdj >= VISIBLE_APP_ADJ
+                                            ? clientAdj : VISIBLE_APP_ADJ;
+                                    if (!client.hidden) {
+                                        app.hidden = false;
+                                    }
+                                    app.adjType = "service";
+                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                                            .REASON_SERVICE_IN_USE;
+                                    app.adjSource = cr.binding.client;
+                                    app.adjTarget = s.name;
+                                }
+                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
+                                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
+                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                    }
                                 }
                             }
-                            int clientAdj = computeOomAdjLocked(
-                                client, myHiddenAdj, TOP_APP, true);
-                            if (adj > clientAdj) {
-                                adj = clientAdj >= VISIBLE_APP_ADJ
-                                        ? clientAdj : VISIBLE_APP_ADJ;
-                                if (!client.hidden) {
-                                    app.hidden = false;
-                                }
+                            ActivityRecord a = cr.activity;
+                            //if (a != null) {
+                            //    Slog.i(TAG, "Connection to " + a ": state=" + a.state);
+                            //}
+                            if (a != null && adj > FOREGROUND_APP_ADJ &&
+                                    (a.state == ActivityState.RESUMED
+                                     || a.state == ActivityState.PAUSING)) {
+                                adj = FOREGROUND_APP_ADJ;
+                                schedGroup = Process.THREAD_GROUP_DEFAULT;
+                                app.hidden = false;
                                 app.adjType = "service";
                                 app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                         .REASON_SERVICE_IN_USE;
-                                app.adjSource = cr.binding.client;
+                                app.adjSource = a;
                                 app.adjTarget = s.name;
                             }
-                            if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
-                                if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
-                                    schedGroup = Process.THREAD_GROUP_DEFAULT;
-                                }
-                            }
-                        }
-                        ActivityRecord a = cr.activity;
-                        //if (a != null) {
-                        //    Slog.i(TAG, "Connection to " + a ": state=" + a.state);
-                        //}
-                        if (a != null && adj > FOREGROUND_APP_ADJ &&
-                                (a.state == ActivityState.RESUMED
-                                 || a.state == ActivityState.PAUSING)) {
-                            adj = FOREGROUND_APP_ADJ;
-                            schedGroup = Process.THREAD_GROUP_DEFAULT;
-                            app.hidden = false;
-                            app.adjType = "service";
-                            app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                                    .REASON_SERVICE_IN_USE;
-                            app.adjSource = a;
-                            app.adjTarget = s.name;
                         }
                     }
                 }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 255fbe3..d5b050b 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -72,8 +72,8 @@
     final HashMap<Intent.FilterComparison, IntentBindRecord> bindings
             = new HashMap<Intent.FilterComparison, IntentBindRecord>();
                             // All active bindings to the service.
-    final HashMap<IBinder, ConnectionRecord> connections
-            = new HashMap<IBinder, ConnectionRecord>();
+    final HashMap<IBinder, ArrayList<ConnectionRecord>> connections
+            = new HashMap<IBinder, ArrayList<ConnectionRecord>>();
                             // IBinder -> ConnectionRecord of all bound clients
 
     ProcessRecord app;      // where this service is running or null.
@@ -296,10 +296,12 @@
         }
         if (connections.size() > 0) {
             pw.print(prefix); pw.println("All Connections:");
-            Iterator<ConnectionRecord> it = connections.values().iterator();
+            Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator();
             while (it.hasNext()) {
-                ConnectionRecord c = it.next();
-                pw.print(prefix); pw.print("  "); pw.println(c);
+                ArrayList<ConnectionRecord> c = it.next();
+                for (int i=0; i<c.size(); i++) {
+                    pw.print(prefix); pw.print("  "); pw.println(c.get(i));
+                }
             }
         }
     }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7f7ef60..194c295 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -163,9 +163,13 @@
     const uint32_t hwFlags = hw.getFlags();
     
     mFormat = format;
-    mReqFormat = format;
     mWidth  = w;
     mHeight = h;
+
+    mReqFormat = format;
+    mReqWidth = w;
+    mReqHeight = h;
+
     mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
     mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
 
@@ -361,16 +365,22 @@
     uint32_t w, h, f;
     { // scope for the lock
         Mutex::Autolock _l(mLock);
-        const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
-        const bool formatChanged    = mReqFormat != reqFormat;
-        mReqWidth  = reqWidth;
-        mReqHeight = reqHeight;
-        mReqFormat = reqFormat;
-        mFixedSize = reqWidth && reqHeight;
-        w = reqWidth  ? reqWidth  : mWidth;
-        h = reqHeight ? reqHeight : mHeight;
-        f = reqFormat ? reqFormat : mFormat;
-        if (fixedSizeChanged || formatChanged) {
+
+        // zero means default
+        if (!reqFormat) reqFormat = mFormat;
+        if (!reqWidth)  reqWidth = mWidth;
+        if (!reqHeight) reqHeight = mHeight;
+
+        w = reqWidth;
+        h = reqHeight;
+        f = reqFormat;
+
+        if ((reqWidth != mReqWidth) || (reqHeight != mReqHeight) ||
+                (reqFormat != mReqFormat)) {
+            mReqWidth  = reqWidth;
+            mReqHeight = reqHeight;
+            mReqFormat = reqFormat;
+
             lcblk->reallocateAllExcept(index);
         }
     }