diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index e561fb92f..33269cbea 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -44,6 +44,7 @@ class Surface; class SurfaceComposerClient; class SharedClient; class SharedBufferClient; +class SurfaceClient; // --------------------------------------------------------------------------- @@ -263,7 +264,7 @@ private: }; // constants - sp mClient; + sp mClient; sp mSurface; SurfaceID mToken; uint32_t mIdentity; diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h index 839603824..102aebc6f 100644 --- a/include/surfaceflinger/SurfaceComposerClient.h +++ b/include/surfaceflinger/SurfaceComposerClient.h @@ -40,7 +40,9 @@ class SharedClient; class ISurfaceComposer; class DisplayInfo; -class SurfaceComposerClient : virtual public RefBase +// --------------------------------------------------------------------------- + +class SurfaceComposerClient : public RefBase { public: SurfaceComposerClient(); @@ -52,10 +54,6 @@ public: // Return the connection of this client sp connection() const; - // Retrieve a client for an existing connection. - static sp - clientForConnection(const sp& conn); - // Forcibly remove connection before all references have gone away. void dispose(); @@ -135,36 +133,45 @@ public: status_t setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy); status_t setPosition(SurfaceID id, int32_t x, int32_t y); status_t setSize(SurfaceID id, uint32_t w, uint32_t h); - void signalServer(); status_t destroySurface(SurfaceID sid); - SharedClient* getSharedClient() const; - private: - SurfaceComposerClient(const sp& sm, - const sp& conn); - - void init(const sp& sm, - const sp& conn); - + virtual void onFirstRef(); inline layer_state_t* get_state_l(SurfaceID id); layer_state_t* lockLayerState(SurfaceID id); inline void unlockLayerState(); mutable Mutex mLock; - layer_state_t* mPrebuiltLayerState; SortedVector mStates; int32_t mTransactionOpen; + layer_state_t* mPrebuiltLayerState; // these don't need to be protected because they never change // after assignment status_t mStatus; - SharedClient* mControl; - sp mControlMemory; sp mClient; - sp mSignalServer; }; +// --------------------------------------------------------------------------- + +class SurfaceClient : public RefBase +{ + // all these attributes are constants + status_t mStatus; + SharedClient* mControl; + sp mControlMemory; + sp mConnection; + sp mSignalServer; + void init(const sp& conn); +public: + explicit SurfaceClient(const sp& conn); + explicit SurfaceClient(const sp& client); + status_t initCheck() const; + SharedClient* getSharedClient() const; + void signalServer() const; +}; + +// --------------------------------------------------------------------------- }; // namespace android #endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index a26733e9d..35a4e8bd0 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -278,14 +278,16 @@ sp SurfaceControl::getSurface() const // Surface // ============================================================================ + Surface::Surface(const sp& surface) - : mClient(surface->mClient), mSurface(surface->mSurface), + : mSurface(surface->mSurface), mToken(surface->mToken), mIdentity(surface->mIdentity), mFormat(surface->mFormat), mFlags(surface->mFlags), mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL), mInitCheck(NO_INIT), mWidth(surface->mWidth), mHeight(surface->mHeight) { + mClient = new SurfaceClient(surface->mClient); init(); } @@ -293,7 +295,7 @@ Surface::Surface(const Parcel& parcel) : mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL), mInitCheck(NO_INIT) { - sp clientBinder = parcel.readStrongBinder(); + sp conn = parcel.readStrongBinder(); mSurface = interface_cast(parcel.readStrongBinder()); mToken = parcel.readInt32(); mIdentity = parcel.readInt32(); @@ -301,12 +303,7 @@ Surface::Surface(const Parcel& parcel) mHeight = parcel.readInt32(); mFormat = parcel.readInt32(); mFlags = parcel.readInt32(); - - // FIXME: what does that mean if clientBinder is NULL here? - if (clientBinder != NULL) { - mClient = SurfaceComposerClient::clientForConnection(clientBinder); - } - + mClient = new SurfaceClient(conn); init(); } @@ -334,7 +331,7 @@ void Surface::init() mBuffers.setCapacity(2); mBuffers.insertAt(0, 2); - if (mClient != 0) { + if (mClient != 0 && mClient->initCheck() == NO_ERROR) { mSharedBufferClient = new SharedBufferClient( mClient->getSharedClient(), mToken, 2, mIdentity); } @@ -364,7 +361,7 @@ Surface::~Surface() status_t Surface::initCheck() const { - if (mToken<0 || mClient==0) { + if (mToken<0 || mClient==0 || mClient->initCheck() != NO_ERROR) { return NO_INIT; } SharedClient const* cblk = mClient->getSharedClient(); @@ -565,8 +562,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) if (err == NO_ERROR) { // FIXME: can we avoid this IPC if we know there is one pending? - const sp& client(mClient); - client->signalServer(); + mClient->signalServer(); } return err; } diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp index 96ed5661b..8d39c8534 100644 --- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp +++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp @@ -17,25 +17,18 @@ #define LOG_TAG "SurfaceComposerClient" #include -#include -#include -#include #include -#include -#include - -#include #include #include -#include +#include #include +#include #include #include #include -#include #include #include @@ -45,69 +38,110 @@ #include #include -#define VERBOSE(...) ((void)0) -//#define VERBOSE LOGD - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) namespace android { - // --------------------------------------------------------------------------- -// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here. -static Mutex gLock; -static sp gSurfaceManager; -static DefaultKeyedVector< sp, wp > gActiveConnections; -static SortedVector > gOpenTransactions; -static sp gServerCblkMemory; -static volatile surface_flinger_cblk_t* gServerCblk; - -static sp getComposerService() +class Composer : public Singleton { - sp sc; - Mutex::Autolock _l(gLock); - if (gSurfaceManager != 0) { - sc = gSurfaceManager; - } else { - // release the lock while we're waiting... - gLock.unlock(); + // these are constants + sp mComposerService; + sp mServerCblkMemory; + surface_flinger_cblk_t volatile* mServerCblk; - sp binder; - sp sm = defaultServiceManager(); - do { - binder = sm->getService(String16("SurfaceFlinger")); - if (binder == 0) { - LOGW("SurfaceFlinger not published, waiting..."); - usleep(500000); // 0.5 s + Mutex mLock; + SortedVector< wp > mActiveConnections; + SortedVector > mOpenTransactions; + + Composer() : Singleton() { + const String16 name("SurfaceFlinger"); + while (getService(name, &mComposerService) != NO_ERROR) { + usleep(250000); + } + mServerCblkMemory = mComposerService->getCblk(); + mServerCblk = static_cast( + mServerCblkMemory->getBase()); + } + + void addClientImpl(const sp& client) { + Mutex::Autolock _l(mLock); + mActiveConnections.add(client); + } + + void removeClientImpl(const sp& client) { + Mutex::Autolock _l(mLock); + mActiveConnections.remove(client); + } + + void openGlobalTransactionImpl() + { + Mutex::Autolock _l(mLock); + if (mOpenTransactions.size()) { + LOGE("openGlobalTransaction() called more than once. skipping."); + return; + } + const size_t N = mActiveConnections.size(); + for (size_t i=0; i client(mActiveConnections[i].promote()); + if (client != 0 && mOpenTransactions.indexOf(client) < 0) { + if (client->openTransaction() == NO_ERROR) { + mOpenTransactions.add(client); + } else { + LOGE("openTransaction on client %p failed", client.get()); + // let it go, it'll fail later when the user + // tries to do something with the transaction + } } - } while(binder == 0); - - // grab the lock again for updating gSurfaceManager - gLock.lock(); - if (gSurfaceManager == 0) { - sc = interface_cast(binder); - gSurfaceManager = sc; - } else { - sc = gSurfaceManager; } } - return sc; + + void closeGlobalTransactionImpl() + { + mLock.lock(); + SortedVector< sp > clients(mOpenTransactions); + mOpenTransactions.clear(); + mLock.unlock(); + + sp sm(mComposerService); + sm->openGlobalTransaction(); + const size_t N = clients.size(); + for (size_t i=0; icloseTransaction(); + } + sm->closeGlobalTransaction(); + } + + friend class Singleton; + +public: + static sp getComposerService() { + return Composer::getInstance().mComposerService; + } + static surface_flinger_cblk_t const volatile * getControlBlock() { + return Composer::getInstance().mServerCblk; + } + static void addClient(const sp& client) { + Composer::getInstance().addClientImpl(client); + } + static void removeClient(const sp& client) { + Composer::getInstance().removeClientImpl(client); + } + static void openGlobalTransaction() { + Composer::getInstance().openGlobalTransactionImpl(); + } + static void closeGlobalTransaction() { + Composer::getInstance().closeGlobalTransactionImpl(); + } +}; + +ANDROID_SINGLETON_STATIC_INSTANCE(Composer); + +static inline sp getComposerService() { + return Composer::getComposerService(); } -static volatile surface_flinger_cblk_t const * get_cblk() -{ - if (gServerCblk == 0) { - sp sm(getComposerService()); - Mutex::Autolock _l(gLock); - if (gServerCblk == 0) { - gServerCblkMemory = sm->getCblk(); - LOGE_IF(gServerCblkMemory==0, "Can't get server control block"); - gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->getBase(); - LOGE_IF(gServerCblk==0, "Can't get server control block address"); - } - } - return gServerCblk; +static inline surface_flinger_cblk_t const volatile * get_cblk() { + return Composer::getControlBlock(); } // --------------------------------------------------------------------------- @@ -120,68 +154,30 @@ static inline int compare_type( const layer_state_t& lhs, } SurfaceComposerClient::SurfaceComposerClient() + : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT) { - sp sm(getComposerService()); - if (sm == 0) { - init(0, 0); - return; - } - - init(sm, sm->createConnection()); - - if (mClient != 0) { - Mutex::Autolock _l(gLock); - VERBOSE("Adding client %p to map", this); - gActiveConnections.add(mClient->asBinder(), this); - } } -SurfaceComposerClient::SurfaceComposerClient( - const sp& sm, const sp& conn) +void SurfaceComposerClient::onFirstRef() { - init(sm, interface_cast(conn)); + sp sm(getComposerService()); + if (sm != 0) { + sp conn = sm->createConnection(); + if (conn != 0) { + mClient = conn; + Composer::addClient(this); + mPrebuiltLayerState = new layer_state_t; + mStatus = NO_ERROR; + } + } } SurfaceComposerClient::~SurfaceComposerClient() { - VERBOSE("Destroying client %p, conn %p", this, mClient.get()); + delete mPrebuiltLayerState; dispose(); } -status_t SurfaceComposerClient::linkToComposerDeath( - const sp& recipient, - void* cookie, uint32_t flags) -{ - sp sm(getComposerService()); - return sm->asBinder()->linkToDeath(recipient, cookie, flags); -} - -void SurfaceComposerClient::init( - const sp& sm, const sp& conn) -{ - VERBOSE("Creating client %p, conn %p", this, conn.get()); - - mPrebuiltLayerState = 0; - mTransactionOpen = 0; - mStatus = NO_ERROR; - mControl = 0; - - mClient = conn; - if (mClient == 0) { - mStatus = NO_INIT; - return; - } - - mControlMemory = mClient->getControlBlock(); - mSignalServer = sm; - mControl = static_cast(mControlMemory->getBase()); -} - -SharedClient* SurfaceComposerClient::getSharedClient() const -{ - return mControl; -} - status_t SurfaceComposerClient::initCheck() const { return mStatus; @@ -192,63 +188,25 @@ sp SurfaceComposerClient::connection() const return (mClient != 0) ? mClient->asBinder() : 0; } -sp -SurfaceComposerClient::clientForConnection(const sp& conn) +status_t SurfaceComposerClient::linkToComposerDeath( + const sp& recipient, + void* cookie, uint32_t flags) { - sp client; - - { // scope for lock - Mutex::Autolock _l(gLock); - client = gActiveConnections.valueFor(conn).promote(); - } - - if (client == 0) { - // Need to make a new client. - sp sm(getComposerService()); - client = new SurfaceComposerClient(sm, conn); - if (client != 0 && client->initCheck() == NO_ERROR) { - Mutex::Autolock _l(gLock); - gActiveConnections.add(conn, client); - //LOGD("we have %d connections", gActiveConnections.size()); - } else { - client.clear(); - } - } - - return client; + sp sm(getComposerService()); + return sm->asBinder()->linkToDeath(recipient, cookie, flags); } void SurfaceComposerClient::dispose() { // this can be called more than once. - - sp controlMemory; - sp client; - - { - Mutex::Autolock _lg(gLock); - Mutex::Autolock _lm(mLock); - - mSignalServer = 0; - - if (mClient != 0) { - client = mClient; - mClient.clear(); - - ssize_t i = gActiveConnections.indexOfKey(client->asBinder()); - if (i >= 0 && gActiveConnections.valueAt(i) == this) { - VERBOSE("Removing client %p from map at %d", this, int(i)); - gActiveConnections.removeItemsAt(i); - } - } - - delete mPrebuiltLayerState; - mPrebuiltLayerState = 0; - controlMemory = mControlMemory; - mControlMemory.clear(); - mControl = 0; - mStatus = NO_INIT; + sp client; + Mutex::Autolock _lm(mLock); + if (mClient != 0) { + Composer::removeClient(this); + client = mClient; // hold ref while lock is held + mClient.clear(); } + mStatus = NO_INIT; } status_t SurfaceComposerClient::getDisplayInfo( @@ -309,12 +267,6 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays() return n; } - -void SurfaceComposerClient::signalServer() -{ - mSignalServer->signal(); -} - sp SurfaceComposerClient::createSurface( int pid, DisplayID display, @@ -331,7 +283,6 @@ sp SurfaceComposerClient::createSurface( return SurfaceComposerClient::createSurface(pid, name, display, w, h, format, flags); - } sp SurfaceComposerClient::createSurface( @@ -377,56 +328,14 @@ status_t SurfaceComposerClient::destroySurface(SurfaceID sid) void SurfaceComposerClient::openGlobalTransaction() { - Mutex::Autolock _l(gLock); - - if (gOpenTransactions.size()) { - LOGE("openGlobalTransaction() called more than once. skipping."); - return; - } - - const size_t N = gActiveConnections.size(); - VERBOSE("openGlobalTransaction (%ld clients)", N); - for (size_t i=0; i client(gActiveConnections.valueAt(i).promote()); - if (client != 0 && gOpenTransactions.indexOf(client) < 0) { - if (client->openTransaction() == NO_ERROR) { - if (gOpenTransactions.add(client) < 0) { - // Ooops! - LOGE( "Unable to add a SurfaceComposerClient " - "to the global transaction set (out of memory?)"); - client->closeTransaction(); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } else { - LOGE("openTransaction on client %p failed", client.get()); - // let it go, it'll fail later when the user - // tries to do something with the transaction - } - } - } + Composer::openGlobalTransaction(); } void SurfaceComposerClient::closeGlobalTransaction() { - gLock.lock(); - SortedVector< sp > clients(gOpenTransactions); - gOpenTransactions.clear(); - gLock.unlock(); - - const size_t N = clients.size(); - VERBOSE("closeGlobalTransaction (%ld clients)", N); - - sp sm(getComposerService()); - sm->openGlobalTransaction(); - for (size_t i=0; icloseTransaction(); - } - sm->closeGlobalTransaction(); - + Composer::closeGlobalTransaction(); } - status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags) { sp sm(getComposerService()); @@ -451,26 +360,16 @@ status_t SurfaceComposerClient::openTransaction() if (mStatus != NO_ERROR) return mStatus; Mutex::Autolock _l(mLock); - VERBOSE( "openTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); mTransactionOpen++; - if (mPrebuiltLayerState == 0) { - mPrebuiltLayerState = new layer_state_t; - } return NO_ERROR; } - status_t SurfaceComposerClient::closeTransaction() { if (mStatus != NO_ERROR) return mStatus; Mutex::Autolock _l(mLock); - - VERBOSE( "closeTransaction (client %p, mTransactionOpen=%d)", - this, mTransactionOpen); - if (mTransactionOpen <= 0) { LOGE( "closeTransaction (client %p, mTransactionOpen=%d) " "called more times than openTransaction()", @@ -502,7 +401,7 @@ layer_state_t* SurfaceComposerClient::get_state_l(SurfaceID index) } // use mPrebuiltLayerState just to find out if we already have it - layer_state_t& dummy = *mPrebuiltLayerState; + layer_state_t& dummy(*mPrebuiltLayerState); dummy.surface = index; ssize_t i = mStates.indexOf(dummy); if (i < 0) { @@ -642,5 +541,42 @@ status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint) return NO_ERROR; } +// ---------------------------------------------------------------------------- + +SurfaceClient::SurfaceClient(const sp& client) + : mStatus(NO_INIT), mControl(0) +{ + if (client != 0) { + sp conn = client->connection(); + init(conn); + } +} +SurfaceClient::SurfaceClient(const sp& conn) + : mStatus(NO_INIT), mControl(0) +{ + init(conn); +} +void SurfaceClient::init(const sp& conn) +{ + mSignalServer = getComposerService(); + sp sf(interface_cast(conn)); + if (sf != 0) { + mConnection = conn; + mControlMemory = sf->getControlBlock(); + mControl = static_cast(mControlMemory->getBase()); + mStatus = NO_ERROR; + } +} +status_t SurfaceClient::initCheck() const { + return mStatus; +} +SharedClient* SurfaceClient::getSharedClient() const { + return mControl; +} +void SurfaceClient::signalServer() const { + mSignalServer->signal(); +} + +// ---------------------------------------------------------------------------- }; // namespace android