summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger_client
diff options
context:
space:
mode:
authorJamie Gennis <jgennis@google.com>2010-07-15 17:29:15 -0700
committerJamie Gennis <jgennis@google.com>2010-07-16 13:03:15 -0700
commitaca4e2287939b4ce3d9e9aced64c5c9641333503 (patch)
tree3193d623b63d097374b2fdd1f800d5f7fe85a5b4 /libs/surfaceflinger_client
parent9e2d6e976b114f42142ba74a3c902b9c073c5629 (diff)
downloadframeworks_native-aca4e2287939b4ce3d9e9aced64c5c9641333503.zip
frameworks_native-aca4e2287939b4ce3d9e9aced64c5c9641333503.tar.gz
frameworks_native-aca4e2287939b4ce3d9e9aced64c5c9641333503.tar.bz2
Re-use existing Surface objects when reading them from parcels.
This change adds a process-global cache of previously deserialized Surface objects so that if a Surface object wrapping the same ISurface gets received again the same Surface can be used. This is important because the 'tail' pointer in the SharedBufferClient is stored only on the client side, and needs to be the same for all the Surface objects wrapping an ISurface instance. This solves the problem by making there only be one Surface object wrapping an ISurface per process. Change-Id: I4bf0b8787885c56277622fca053022d2bb638902
Diffstat (limited to 'libs/surfaceflinger_client')
-rw-r--r--libs/surfaceflinger_client/Surface.cpp35
1 files changed, 28 insertions, 7 deletions
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index dc6332c..1de3a4f 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()