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
This commit is contained in:
parent
9e2d6e976b
commit
aca4e22879
@ -20,6 +20,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <utils/KeyedVector.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include <utils/threads.h>
|
#include <utils/threads.h>
|
||||||
|
|
||||||
@ -147,8 +148,7 @@ public:
|
|||||||
static status_t writeToParcel(
|
static status_t writeToParcel(
|
||||||
const sp<Surface>& control, Parcel* parcel);
|
const sp<Surface>& control, Parcel* parcel);
|
||||||
|
|
||||||
static sp<Surface> readFromParcel(
|
static sp<Surface> readFromParcel(const Parcel& data);
|
||||||
const Parcel& data, const sp<Surface>& other);
|
|
||||||
|
|
||||||
static bool isValid(const sp<Surface>& surface) {
|
static bool isValid(const sp<Surface>& surface) {
|
||||||
return (surface != 0) && surface->isValid();
|
return (surface != 0) && surface->isValid();
|
||||||
@ -244,6 +244,8 @@ private:
|
|||||||
uint32_t *pWidth, uint32_t *pHeight,
|
uint32_t *pWidth, uint32_t *pHeight,
|
||||||
uint32_t *pFormat, uint32_t *pUsage) const;
|
uint32_t *pFormat, uint32_t *pUsage) const;
|
||||||
|
|
||||||
|
static void cleanCachedSurfaces();
|
||||||
|
|
||||||
class BufferInfo {
|
class BufferInfo {
|
||||||
uint32_t mWidth;
|
uint32_t mWidth;
|
||||||
uint32_t mHeight;
|
uint32_t mHeight;
|
||||||
@ -298,6 +300,10 @@ private:
|
|||||||
// Inherently thread-safe
|
// Inherently thread-safe
|
||||||
mutable Mutex mSurfaceLock;
|
mutable Mutex mSurfaceLock;
|
||||||
mutable Mutex mApiLock;
|
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
|
}; // namespace android
|
||||||
|
@ -374,15 +374,36 @@ status_t Surface::writeToParcel(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<Surface> Surface::readFromParcel(
|
|
||||||
const Parcel& data, const sp<Surface>& other)
|
Mutex Surface::sCachedSurfacesLock;
|
||||||
{
|
DefaultKeyedVector<wp<IBinder>, wp<Surface> > Surface::sCachedSurfaces(wp<Surface>(0));
|
||||||
sp<Surface> result(other);
|
|
||||||
|
sp<Surface> Surface::readFromParcel(const Parcel& data) {
|
||||||
|
Mutex::Autolock _l(sCachedSurfacesLock);
|
||||||
sp<IBinder> binder(data.readStrongBinder());
|
sp<IBinder> binder(data.readStrongBinder());
|
||||||
if (other==0 || binder != other->mSurface->asBinder()) {
|
sp<Surface> surface = sCachedSurfaces.valueFor(binder).promote();
|
||||||
result = new Surface(data, binder);
|
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()
|
void Surface::init()
|
||||||
|
Loading…
Reference in New Issue
Block a user