Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d17592c authored by Mathias Agopian's avatar Mathias Agopian Committed by Android Git Automerger
Browse files

am 64ff6ab4: Merge "more clean-up of Surfaceflinger\'s client management" into kraken

parents 329ffd76 0208f296
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ class Surface;
class SurfaceComposerClient;
class SurfaceComposerClient;
class SharedClient;
class SharedClient;
class SharedBufferClient;
class SharedBufferClient;
class SurfaceClient;


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


@@ -263,7 +264,7 @@ private:
    };
    };


    // constants
    // constants
    sp<SurfaceComposerClient>   mClient;
    sp<SurfaceClient>           mClient;
    sp<ISurface>                mSurface;
    sp<ISurface>                mSurface;
    SurfaceID                   mToken;
    SurfaceID                   mToken;
    uint32_t                    mIdentity;
    uint32_t                    mIdentity;
+25 −18
Original line number Original line Diff line number Diff line
@@ -40,7 +40,9 @@ class SharedClient;
class ISurfaceComposer;
class ISurfaceComposer;
class DisplayInfo;
class DisplayInfo;


class SurfaceComposerClient : virtual public RefBase
// ---------------------------------------------------------------------------

class SurfaceComposerClient : public RefBase
{
{
public:    
public:    
                SurfaceComposerClient();
                SurfaceComposerClient();
@@ -52,10 +54,6 @@ public:
    // Return the connection of this client
    // Return the connection of this client
    sp<IBinder> connection() const;
    sp<IBinder> connection() const;
    
    
    // Retrieve a client for an existing connection.
    static sp<SurfaceComposerClient>
                clientForConnection(const sp<IBinder>& conn);

    // Forcibly remove connection before all references have gone away.
    // Forcibly remove connection before all references have gone away.
    void        dispose();
    void        dispose();


@@ -135,36 +133,45 @@ public:
    status_t    setMatrix(SurfaceID id, float dsdx, float dtdx, float dsdy, float dtdy);
    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    setPosition(SurfaceID id, int32_t x, int32_t y);
    status_t    setSize(SurfaceID id, uint32_t w, uint32_t h);
    status_t    setSize(SurfaceID id, uint32_t w, uint32_t h);
    void        signalServer();
    status_t    destroySurface(SurfaceID sid);
    status_t    destroySurface(SurfaceID sid);


    SharedClient*   getSharedClient() const;

private:
private:
    SurfaceComposerClient(const sp<ISurfaceComposer>& sm,
    virtual void onFirstRef();
            const sp<IBinder>& conn);

    void        init(const sp<ISurfaceComposer>& sm,
                    const sp<ISurfaceFlingerClient>& conn);

    inline layer_state_t*   get_state_l(SurfaceID id);
    inline layer_state_t*   get_state_l(SurfaceID id);
    layer_state_t*          lockLayerState(SurfaceID id);
    layer_state_t*          lockLayerState(SurfaceID id);
    inline void             unlockLayerState();
    inline void             unlockLayerState();


    mutable     Mutex                               mLock;
    mutable     Mutex                               mLock;
                layer_state_t*                      mPrebuiltLayerState;
                SortedVector<layer_state_t>         mStates;
                SortedVector<layer_state_t>         mStates;
                int32_t                             mTransactionOpen;
                int32_t                             mTransactionOpen;
                layer_state_t*                      mPrebuiltLayerState;


                // these don't need to be protected because they never change
                // these don't need to be protected because they never change
                // after assignment
                // after assignment
                status_t                    mStatus;
                status_t                    mStatus;
                sp<ISurfaceFlingerClient>   mClient;
};

// ---------------------------------------------------------------------------

class SurfaceClient : public RefBase
{
    // all these attributes are constants
    status_t                    mStatus;
    SharedClient*               mControl;
    SharedClient*               mControl;
    sp<IMemoryHeap>             mControlMemory;
    sp<IMemoryHeap>             mControlMemory;
                sp<ISurfaceFlingerClient>   mClient;
    sp<IBinder>                 mConnection;
    sp<ISurfaceComposer>        mSignalServer;
    sp<ISurfaceComposer>        mSignalServer;
    void init(const sp<IBinder>& conn);
public:
    explicit SurfaceClient(const sp<IBinder>& conn);
    explicit SurfaceClient(const sp<SurfaceComposerClient>& client);
    status_t initCheck() const;
    SharedClient* getSharedClient() const;
    void signalServer() const;
};
};


// ---------------------------------------------------------------------------
}; // namespace android
}; // namespace android


#endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
#endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
+8 −12
Original line number Original line Diff line number Diff line
@@ -278,14 +278,16 @@ sp<Surface> SurfaceControl::getSurface() const
//  Surface
//  Surface
// ============================================================================
// ============================================================================



Surface::Surface(const sp<SurfaceControl>& surface)
Surface::Surface(const sp<SurfaceControl>& surface)
    : mClient(surface->mClient), mSurface(surface->mSurface),
    : mSurface(surface->mSurface),
      mToken(surface->mToken), mIdentity(surface->mIdentity),
      mToken(surface->mToken), mIdentity(surface->mIdentity),
      mFormat(surface->mFormat), mFlags(surface->mFlags),
      mFormat(surface->mFormat), mFlags(surface->mFlags),
      mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
      mBufferMapper(GraphicBufferMapper::get()), mSharedBufferClient(NULL),
      mInitCheck(NO_INIT),
      mInitCheck(NO_INIT),
      mWidth(surface->mWidth), mHeight(surface->mHeight)
      mWidth(surface->mWidth), mHeight(surface->mHeight)
{
{
    mClient = new SurfaceClient(surface->mClient);
    init();
    init();
}
}


@@ -293,7 +295,7 @@ Surface::Surface(const Parcel& parcel)
    :  mBufferMapper(GraphicBufferMapper::get()),
    :  mBufferMapper(GraphicBufferMapper::get()),
       mSharedBufferClient(NULL), mInitCheck(NO_INIT)
       mSharedBufferClient(NULL), mInitCheck(NO_INIT)
{
{
    sp<IBinder> clientBinder = parcel.readStrongBinder();
    sp<IBinder> conn = parcel.readStrongBinder();
    mSurface    = interface_cast<ISurface>(parcel.readStrongBinder());
    mSurface    = interface_cast<ISurface>(parcel.readStrongBinder());
    mToken      = parcel.readInt32();
    mToken      = parcel.readInt32();
    mIdentity   = parcel.readInt32();
    mIdentity   = parcel.readInt32();
@@ -301,12 +303,7 @@ Surface::Surface(const Parcel& parcel)
    mHeight     = parcel.readInt32();
    mHeight     = parcel.readInt32();
    mFormat     = parcel.readInt32();
    mFormat     = parcel.readInt32();
    mFlags      = parcel.readInt32();
    mFlags      = parcel.readInt32();

    mClient = new SurfaceClient(conn);
    // FIXME: what does that mean if clientBinder is NULL here?
    if (clientBinder != NULL) {
        mClient = SurfaceComposerClient::clientForConnection(clientBinder);
    }

    init();
    init();
}
}


@@ -334,7 +331,7 @@ void Surface::init()
    mBuffers.setCapacity(2);
    mBuffers.setCapacity(2);
    mBuffers.insertAt(0, 2);
    mBuffers.insertAt(0, 2);


    if (mClient != 0) {
    if (mClient != 0 && mClient->initCheck() == NO_ERROR) {
        mSharedBufferClient = new SharedBufferClient(
        mSharedBufferClient = new SharedBufferClient(
                mClient->getSharedClient(), mToken, 2, mIdentity);
                mClient->getSharedClient(), mToken, 2, mIdentity);
    }
    }
@@ -364,7 +361,7 @@ Surface::~Surface()


status_t Surface::initCheck() const
status_t Surface::initCheck() const
{
{
    if (mToken<0 || mClient==0) {
    if (mToken<0 || mClient==0 || mClient->initCheck() != NO_ERROR) {
        return NO_INIT;
        return NO_INIT;
    }
    }
    SharedClient const* cblk = mClient->getSharedClient();
    SharedClient const* cblk = mClient->getSharedClient();
@@ -565,8 +562,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)


    if (err == NO_ERROR) {
    if (err == NO_ERROR) {
        // FIXME: can we avoid this IPC if we know there is one pending?
        // FIXME: can we avoid this IPC if we know there is one pending?
        const sp<SurfaceComposerClient>& client(mClient);
        mClient->signalServer();
        client->signalServer();
    }
    }
    return err;
    return err;
}
}
+162 −226
Original line number Original line Diff line number Diff line
@@ -17,25 +17,18 @@
#define LOG_TAG "SurfaceComposerClient"
#define LOG_TAG "SurfaceComposerClient"


#include <stdint.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>


#include <cutils/memory.h>

#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/SortedVector.h>
#include <utils/Log.h>
#include <utils/Log.h>
#include <utils/Singleton.h>


#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <binder/IMemory.h>
#include <binder/IMemory.h>


#include <ui/DisplayInfo.h>
#include <ui/DisplayInfo.h>
#include <ui/Rect.h>


#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/ISurfaceFlingerClient.h>
#include <surfaceflinger/ISurfaceFlingerClient.h>
@@ -45,69 +38,110 @@
#include <private/surfaceflinger/LayerState.h>
#include <private/surfaceflinger/LayerState.h>
#include <private/surfaceflinger/SharedBufferStack.h>
#include <private/surfaceflinger/SharedBufferStack.h>


#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 {
namespace android {

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


// Must not be holding SurfaceComposerClient::mLock when acquiring gLock here.
class Composer : public Singleton<Composer>
static Mutex                                                gLock;
{
static sp<ISurfaceComposer>                                 gSurfaceManager;
    // these are constants
static DefaultKeyedVector< sp<IBinder>, wp<SurfaceComposerClient> > gActiveConnections;
    sp<ISurfaceComposer> mComposerService;
static SortedVector<sp<SurfaceComposerClient> >             gOpenTransactions;
    sp<IMemoryHeap> mServerCblkMemory;
static sp<IMemoryHeap>                                      gServerCblkMemory;
    surface_flinger_cblk_t volatile* mServerCblk;
static volatile surface_flinger_cblk_t*                     gServerCblk;

    Mutex mLock;
    SortedVector< wp<SurfaceComposerClient> > mActiveConnections;
    SortedVector<sp<SurfaceComposerClient> > mOpenTransactions;

    Composer() : Singleton<Composer>() {
        const String16 name("SurfaceFlinger");
        while (getService(name, &mComposerService) != NO_ERROR) {
            usleep(250000);
        }
        mServerCblkMemory = mComposerService->getCblk();
        mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(
                mServerCblkMemory->getBase());
    }

    void addClientImpl(const sp<SurfaceComposerClient>& client) {
        Mutex::Autolock _l(mLock);
        mActiveConnections.add(client);
    }


static sp<ISurfaceComposer> getComposerService()
    void removeClientImpl(const sp<SurfaceComposerClient>& client) {
        Mutex::Autolock _l(mLock);
        mActiveConnections.remove(client);
    }

    void openGlobalTransactionImpl()
    {
    {
    sp<ISurfaceComposer> sc;
        Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(gLock);
        if (mOpenTransactions.size()) {
    if (gSurfaceManager != 0) {
            LOGE("openGlobalTransaction() called more than once. skipping.");
        sc = gSurfaceManager;
            return;
    } else {
        }
        // release the lock while we're waiting...
        const size_t N = mActiveConnections.size();
        gLock.unlock();
        for (size_t i=0; i<N; i++) {

            sp<SurfaceComposerClient> client(mActiveConnections[i].promote());
        sp<IBinder> binder;
            if (client != 0 && mOpenTransactions.indexOf(client) < 0) {
        sp<IServiceManager> sm = defaultServiceManager();
                if (client->openTransaction() == NO_ERROR) {
        do {
                    mOpenTransactions.add(client);
            binder = sm->getService(String16("SurfaceFlinger"));
            if (binder == 0) {
                LOGW("SurfaceFlinger not published, waiting...");
                usleep(500000); // 0.5 s
            }
        } while(binder == 0);

        // grab the lock again for updating gSurfaceManager
        gLock.lock();
        if (gSurfaceManager == 0) {
            sc = interface_cast<ISurfaceComposer>(binder);
            gSurfaceManager = sc;
                } else {
                } else {
            sc = gSurfaceManager;
                    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
                }
            }
            }
        }
        }
    return sc;
    }
    }


static volatile surface_flinger_cblk_t const * get_cblk()
    void closeGlobalTransactionImpl()
    {
    {
    if (gServerCblk == 0) {
        mLock.lock();
        sp<ISurfaceComposer> sm(getComposerService());
            SortedVector< sp<SurfaceComposerClient> > clients(mOpenTransactions);
        Mutex::Autolock _l(gLock);
            mOpenTransactions.clear();
        if (gServerCblk == 0) {
        mLock.unlock();
            gServerCblkMemory = sm->getCblk();

            LOGE_IF(gServerCblkMemory==0, "Can't get server control block");
        sp<ISurfaceComposer> sm(mComposerService);
            gServerCblk = (surface_flinger_cblk_t *)gServerCblkMemory->getBase();
        sm->openGlobalTransaction();
            LOGE_IF(gServerCblk==0, "Can't get server control block address");
            const size_t N = clients.size();
            for (size_t i=0; i<N; i++) {
                clients[i]->closeTransaction();
            }
        sm->closeGlobalTransaction();
    }

    friend class Singleton<Composer>;

public:
    static sp<ISurfaceComposer> getComposerService() {
        return Composer::getInstance().mComposerService;
    }
    static surface_flinger_cblk_t const volatile * getControlBlock() {
        return Composer::getInstance().mServerCblk;
    }
    static void addClient(const sp<SurfaceComposerClient>& client) {
        Composer::getInstance().addClientImpl(client);
    }
    static void removeClient(const sp<SurfaceComposerClient>& client) {
        Composer::getInstance().removeClientImpl(client);
    }
    }
    static void openGlobalTransaction() {
        Composer::getInstance().openGlobalTransactionImpl();
    }
    }
    return gServerCblk;
    static void closeGlobalTransaction() {
        Composer::getInstance().closeGlobalTransactionImpl();
    }
};

ANDROID_SINGLETON_STATIC_INSTANCE(Composer);

static inline sp<ISurfaceComposer> getComposerService() {
    return Composer::getComposerService();
}

static inline surface_flinger_cblk_t const volatile * get_cblk() {
    return Composer::getControlBlock();
}
}


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
@@ -120,66 +154,28 @@ static inline int compare_type( const layer_state_t& lhs,
}
}


SurfaceComposerClient::SurfaceComposerClient()
SurfaceComposerClient::SurfaceComposerClient()
    : mTransactionOpen(0), mPrebuiltLayerState(0), mStatus(NO_INIT)
{
{
    sp<ISurfaceComposer> sm(getComposerService());
    if (sm == 0) {
        init(0, 0);
        return;
}
}


    init(sm, sm->createConnection());
void SurfaceComposerClient::onFirstRef()

    if (mClient != 0) {
        Mutex::Autolock _l(gLock);
        VERBOSE("Adding client %p to map", this);
        gActiveConnections.add(mClient->asBinder(), this);
    }
}

SurfaceComposerClient::SurfaceComposerClient(
        const sp<ISurfaceComposer>& sm, const sp<IBinder>& conn)
{
    init(sm, interface_cast<ISurfaceFlingerClient>(conn));
}

SurfaceComposerClient::~SurfaceComposerClient()
{
    VERBOSE("Destroying client %p, conn %p", this, mClient.get());
    dispose();
}

status_t SurfaceComposerClient::linkToComposerDeath(
        const sp<IBinder::DeathRecipient>& recipient,
        void* cookie, uint32_t flags)
{
{
    sp<ISurfaceComposer> sm(getComposerService());
    sp<ISurfaceComposer> sm(getComposerService());
    return sm->asBinder()->linkToDeath(recipient, cookie, flags);    
    if (sm != 0) {
}
        sp<ISurfaceFlingerClient> conn = sm->createConnection();

        if (conn != 0) {
void SurfaceComposerClient::init(
        const sp<ISurfaceComposer>& sm, const sp<ISurfaceFlingerClient>& conn)
{
    VERBOSE("Creating client %p, conn %p", this, conn.get());

    mPrebuiltLayerState = 0;
    mTransactionOpen = 0;
    mStatus = NO_ERROR;
    mControl = 0;

            mClient = conn;
            mClient = conn;
    if (mClient == 0) {
            Composer::addClient(this);
        mStatus = NO_INIT;
            mPrebuiltLayerState = new layer_state_t;
        return;
            mStatus = NO_ERROR;
        }
    }
    }

    mControlMemory = mClient->getControlBlock();
    mSignalServer = sm;
    mControl = static_cast<SharedClient *>(mControlMemory->getBase());
}
}


SharedClient* SurfaceComposerClient::getSharedClient() const
SurfaceComposerClient::~SurfaceComposerClient()
{
{
    return mControl;
    delete mPrebuiltLayerState;
    dispose();
}
}


status_t SurfaceComposerClient::initCheck() const
status_t SurfaceComposerClient::initCheck() const
@@ -192,64 +188,26 @@ sp<IBinder> SurfaceComposerClient::connection() const
    return (mClient != 0) ? mClient->asBinder() : 0;
    return (mClient != 0) ? mClient->asBinder() : 0;
}
}


sp<SurfaceComposerClient>
status_t SurfaceComposerClient::linkToComposerDeath(
SurfaceComposerClient::clientForConnection(const sp<IBinder>& conn)
        const sp<IBinder::DeathRecipient>& recipient,
        void* cookie, uint32_t flags)
{
{
    sp<SurfaceComposerClient> client;

    { // scope for lock
        Mutex::Autolock _l(gLock);
        client = gActiveConnections.valueFor(conn).promote();
    }

    if (client == 0) {
        // Need to make a new client.
    sp<ISurfaceComposer> sm(getComposerService());
    sp<ISurfaceComposer> sm(getComposerService());
        client = new SurfaceComposerClient(sm, conn);
    return sm->asBinder()->linkToDeath(recipient, cookie, flags);
        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;
}
}


void SurfaceComposerClient::dispose()
void SurfaceComposerClient::dispose()
{
{
    // this can be called more than once.
    // this can be called more than once.

    sp<IMemoryHeap>             controlMemory;
    sp<ISurfaceFlingerClient> client;
    sp<ISurfaceFlingerClient> client;

    {
        Mutex::Autolock _lg(gLock);
    Mutex::Autolock _lm(mLock);
    Mutex::Autolock _lm(mLock);

        mSignalServer = 0;

    if (mClient != 0) {
    if (mClient != 0) {
            client = mClient;
        Composer::removeClient(this);
        client = mClient; // hold ref while lock is held
        mClient.clear();
        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;
    mStatus = NO_INIT;
}
}
}


status_t SurfaceComposerClient::getDisplayInfo(
status_t SurfaceComposerClient::getDisplayInfo(
        DisplayID dpy, DisplayInfo* info)
        DisplayID dpy, DisplayInfo* info)
@@ -309,12 +267,6 @@ ssize_t SurfaceComposerClient::getNumberOfDisplays()
    return n;
    return n;
}
}



void SurfaceComposerClient::signalServer()
{
    mSignalServer->signal();
}

sp<SurfaceControl> SurfaceComposerClient::createSurface(
sp<SurfaceControl> SurfaceComposerClient::createSurface(
        int pid,
        int pid,
        DisplayID display,
        DisplayID display,
@@ -331,7 +283,6 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(


    return SurfaceComposerClient::createSurface(pid, name, display,
    return SurfaceComposerClient::createSurface(pid, name, display,
            w, h, format, flags);
            w, h, format, flags);

}
}


sp<SurfaceControl> SurfaceComposerClient::createSurface(
sp<SurfaceControl> SurfaceComposerClient::createSurface(
@@ -377,55 +328,13 @@ status_t SurfaceComposerClient::destroySurface(SurfaceID sid)


void SurfaceComposerClient::openGlobalTransaction()
void SurfaceComposerClient::openGlobalTransaction()
{
{
    Mutex::Autolock _l(gLock);
    Composer::openGlobalTransaction();

    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<N; i++) {
        sp<SurfaceComposerClient> 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
            }
        }
    }
}
}


void SurfaceComposerClient::closeGlobalTransaction()
void SurfaceComposerClient::closeGlobalTransaction()
{
{
    gLock.lock();
    Composer::closeGlobalTransaction();
        SortedVector< sp<SurfaceComposerClient> > clients(gOpenTransactions);
        gOpenTransactions.clear();
    gLock.unlock();

    const size_t N = clients.size();
    VERBOSE("closeGlobalTransaction (%ld clients)", N);

    sp<ISurfaceComposer> sm(getComposerService());
    sm->openGlobalTransaction();
    for (size_t i=0; i<N; i++) {
        clients[i]->closeTransaction();
}
}
    sm->closeGlobalTransaction();

}



status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
{
{
@@ -451,26 +360,16 @@ status_t SurfaceComposerClient::openTransaction()
    if (mStatus != NO_ERROR)
    if (mStatus != NO_ERROR)
        return mStatus;
        return mStatus;
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    VERBOSE(   "openTransaction (client %p, mTransactionOpen=%d)",
            this, mTransactionOpen);
    mTransactionOpen++;
    mTransactionOpen++;
    if (mPrebuiltLayerState == 0) {
        mPrebuiltLayerState = new layer_state_t;
    }
    return NO_ERROR;
    return NO_ERROR;
}
}



status_t SurfaceComposerClient::closeTransaction()
status_t SurfaceComposerClient::closeTransaction()
{
{
    if (mStatus != NO_ERROR)
    if (mStatus != NO_ERROR)
        return mStatus;
        return mStatus;


    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);

    VERBOSE(   "closeTransaction (client %p, mTransactionOpen=%d)",
            this, mTransactionOpen);

    if (mTransactionOpen <= 0) {
    if (mTransactionOpen <= 0) {
        LOGE(   "closeTransaction (client %p, mTransactionOpen=%d) "
        LOGE(   "closeTransaction (client %p, mTransactionOpen=%d) "
                "called more times than openTransaction()",
                "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
    // use mPrebuiltLayerState just to find out if we already have it
    layer_state_t& dummy = *mPrebuiltLayerState;
    layer_state_t& dummy(*mPrebuiltLayerState);
    dummy.surface = index;
    dummy.surface = index;
    ssize_t i = mStates.indexOf(dummy);
    ssize_t i = mStates.indexOf(dummy);
    if (i < 0) {
    if (i < 0) {
@@ -642,5 +541,42 @@ status_t SurfaceComposerClient::setFreezeTint(SurfaceID id, uint32_t tint)
    return NO_ERROR;
    return NO_ERROR;
}
}


// ----------------------------------------------------------------------------

SurfaceClient::SurfaceClient(const sp<SurfaceComposerClient>& client)
    : mStatus(NO_INIT), mControl(0)
{
    if (client != 0) {
        sp<IBinder> conn = client->connection();
        init(conn);
    }
}
SurfaceClient::SurfaceClient(const sp<IBinder>& conn)
    : mStatus(NO_INIT), mControl(0)
{
    init(conn);
}
void SurfaceClient::init(const sp<IBinder>& conn)
{
    mSignalServer = getComposerService();
    sp<ISurfaceFlingerClient> sf(interface_cast<ISurfaceFlingerClient>(conn));
    if (sf != 0) {
        mConnection = conn;
        mControlMemory = sf->getControlBlock();
        mControl = static_cast<SharedClient *>(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
}; // namespace android