diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 4fd068159..294c867c3 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 
@@ -147,8 +148,7 @@ public:
     static status_t writeToParcel(
             const sp<Surface>& control, Parcel* parcel);
 
-    static sp<Surface> readFromParcel(
-            const Parcel& data, const sp<Surface>& other);
+    static sp<Surface> readFromParcel(const Parcel& data);
 
     static bool isValid(const sp<Surface>& surface) {
         return (surface != 0) && surface->isValid();
@@ -244,6 +244,8 @@ private:
             uint32_t *pWidth, uint32_t *pHeight,
             uint32_t *pFormat, uint32_t *pUsage) const;
 
+    static void cleanCachedSurfaces();
+
     class BufferInfo {
         uint32_t mWidth;
         uint32_t mHeight;
@@ -298,6 +300,10 @@ private:
     // Inherently thread-safe
     mutable Mutex               mSurfaceLock;
     mutable Mutex               mApiLock;
+
+    // A cache of Surface objects that have been deserialized into this process.
+    static Mutex sCachedSurfacesLock;
+    static DefaultKeyedVector<wp<IBinder>, wp<Surface> > sCachedSurfaces;
 };
 
 }; // namespace android
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index dc6332cb6..1de3a4fb7 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -374,15 +374,36 @@ status_t Surface::writeToParcel(
 
 }
 
-sp<Surface> Surface::readFromParcel(
-        const Parcel& data, const sp<Surface>& other)
-{
-    sp<Surface> result(other);
+
+Mutex Surface::sCachedSurfacesLock;
+DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces(wp<Surface>(0));
+
+sp<Surface> Surface::readFromParcel(const Parcel& data) {
+    Mutex::Autolock _l(sCachedSurfacesLock);
     sp<IBinder> binder(data.readStrongBinder());
-    if (other==0 || binder != other->mSurface->asBinder()) {
-        result = new Surface(data, binder);
+    sp<Surface> surface = sCachedSurfaces.valueFor(binder).promote();
+    if (surface == 0) {
+       surface = new Surface(data, binder);
+       sCachedSurfaces.add(binder, surface);
+    } else {
+        LOGW("Reusing surface!");
+    }
+    if (surface->mSurface == 0) {
+      surface = 0;
+    }
+    cleanCachedSurfaces();
+    return surface;
+}
+
+// Remove the stale entries from the surface cache.  This should only be called
+// with sCachedSurfacesLock held.
+void Surface::cleanCachedSurfaces() {
+    for (int i = sCachedSurfaces.size()-1; i >= 0; --i) {
+        wp<Surface> s(sCachedSurfaces.valueAt(i));
+        if (s == 0 || s.promote() == 0) {
+            sCachedSurfaces.removeItemsAt(i);
+        }
     }
-    return result;
 }
 
 void Surface::init()