am 593c05ce: clean-up client management.

This commit is contained in:
Mathias Agopian
2010-06-04 19:15:38 -07:00
committed by Android Git Automerger
15 changed files with 260 additions and 614 deletions

View File

@@ -14,7 +14,6 @@ LOCAL_SRC_FILES:= \
MessageQueue.cpp \ MessageQueue.cpp \
SurfaceFlinger.cpp \ SurfaceFlinger.cpp \
TextureManager.cpp \ TextureManager.cpp \
Tokenizer.cpp \
Transform.cpp Transform.cpp
LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"

View File

@@ -47,9 +47,9 @@ template <typename T> inline T min(T a, T b) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Layer::Layer(SurfaceFlinger* flinger,
const sp<Client>& client, int32_t i) DisplayID display, const sp<Client>& client)
: LayerBaseClient(flinger, display, client, i), : LayerBaseClient(flinger, display, client),
lcblk(NULL), lcblk(NULL),
mSecure(false), mSecure(false),
mNeedsBlending(true), mNeedsBlending(true),
@@ -58,13 +58,6 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
mBufferManager(mTextureManager), mBufferManager(mTextureManager),
mWidth(0), mHeight(0), mFixedSize(false) mWidth(0), mHeight(0), mFixedSize(false)
{ {
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
lcblk = new SharedBufferServer(
client->ctrlblk, i, mBufferManager.getDefaultBufferCount(),
getIdentity());
mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
} }
Layer::~Layer() Layer::~Layer()
@@ -77,13 +70,32 @@ Layer::~Layer()
delete lcblk; delete lcblk;
} }
// TODO: get rid of this
void Layer::setToken(int32_t token)
{
sp<Client> ourClient(client.promote());
mToken = token;
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
lcblk = new SharedBufferServer(
ourClient->ctrlblk, token, mBufferManager.getDefaultBufferCount(),
getIdentity());
mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered // called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list // in the purgatory list
void Layer::onRemoved() void Layer::onRemoved()
{ {
sp<Client> ourClient(client.promote());
if (ourClient != 0) {
// wake up the condition // wake up the condition
lcblk->setStatus(NO_INIT); lcblk->setStatus(NO_INIT);
} }
}
sp<LayerBaseClient::Surface> Layer::createSurface() const sp<LayerBaseClient::Surface> Layer::createSurface() const
{ {
@@ -140,7 +152,7 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
mNeedsDithering = layerRedsize > displayRedSize; mNeedsDithering = layerRedsize > displayRedSize;
mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); mSurface = new SurfaceLayer(mFlinger, this);
return NO_ERROR; return NO_ERROR;
} }
@@ -391,8 +403,11 @@ uint32_t Layer::doTransaction(uint32_t flags)
// a buffer, it'll get the new size. // a buffer, it'll get the new size.
setBufferSize(temp.requested_w, temp.requested_h); setBufferSize(temp.requested_w, temp.requested_h);
sp<Client> ourClient(client.promote());
if (ourClient != 0) {
// all buffers need reallocation // all buffers need reallocation
lcblk->reallocateAll(); lcblk->reallocateAll();
}
} else { } else {
// record the new size // record the new size
setBufferSize(temp.requested_w, temp.requested_h); setBufferSize(temp.requested_w, temp.requested_h);
@@ -427,6 +442,13 @@ bool Layer::isFixedSize() const {
void Layer::lockPageFlip(bool& recomputeVisibleRegions) void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{ {
sp<Client> ourClient(client.promote());
if (ourClient == 0) {
// client died
recomputeVisibleRegions = true;
return;
}
ssize_t buf = lcblk->retireAndLock(); ssize_t buf = lcblk->retireAndLock();
if (buf == NOT_ENOUGH_DATA) { if (buf == NOT_ENOUGH_DATA) {
// NOTE: This is not an error, it simply means there is nothing to // NOTE: This is not an error, it simply means there is nothing to
@@ -538,10 +560,13 @@ void Layer::unlockPageFlip(
void Layer::finishPageFlip() void Layer::finishPageFlip()
{ {
sp<Client> ourClient(client.promote());
if (ourClient != 0) {
int buf = mBufferManager.getActiveBufferIndex(); int buf = mBufferManager.getActiveBufferIndex();
status_t err = lcblk->unlock( buf ); status_t err = lcblk->unlock( buf );
LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf); LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
} }
}
void Layer::dump(String8& result, char* buffer, size_t SIZE) const void Layer::dump(String8& result, char* buffer, size_t SIZE) const
@@ -707,8 +732,8 @@ status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
SurfaceID id, const sp<Layer>& owner) const sp<Layer>& owner)
: Surface(flinger, id, owner->getIdentity(), owner) : Surface(flinger, owner->getIdentity(), owner)
{ {
} }

View File

@@ -50,7 +50,7 @@ public:
SharedBufferServer* lcblk; SharedBufferServer* lcblk;
Layer(SurfaceFlinger* flinger, DisplayID display, Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i); const sp<Client>& client);
virtual ~Layer(); virtual ~Layer();
@@ -96,8 +96,7 @@ private:
class SurfaceLayer : public LayerBaseClient::Surface { class SurfaceLayer : public LayerBaseClient::Surface {
public: public:
SurfaceLayer(const sp<SurfaceFlinger>& flinger, SurfaceLayer(const sp<SurfaceFlinger>& flinger, const sp<Layer>& owner);
SurfaceID id, const sp<Layer>& owner);
~SurfaceLayer(); ~SurfaceLayer();
private: private:
virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
@@ -189,6 +188,12 @@ private:
uint32_t mReqHeight; uint32_t mReqHeight;
uint32_t mReqFormat; uint32_t mReqFormat;
bool mFixedSize; bool mFixedSize;
// TODO: get rid of this
private:
virtual void setToken(int32_t token);
virtual int32_t getToken() const { return mToken; }
int32_t mToken;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -488,37 +488,20 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
int32_t LayerBaseClient::sIdentity = 1; int32_t LayerBaseClient::sIdentity = 1;
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display, LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i) const sp<Client>& client)
: LayerBase(flinger, display), client(client), mIndex(i), : LayerBase(flinger, display), client(client),
mIdentity(uint32_t(android_atomic_inc(&sIdentity))) mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{ {
} }
void LayerBaseClient::onFirstRef()
{
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
}
}
LayerBaseClient::~LayerBaseClient() LayerBaseClient::~LayerBaseClient()
{ {
sp<Client> client(this->client.promote()); sp<Client> c(client.promote());
if (client != 0) { if (c != 0) {
client->free(mIndex); c->free(this);
} }
} }
ssize_t LayerBaseClient::serverIndex() const
{
sp<Client> client(this->client.promote());
if (client != 0) {
return (client->cid<<16)|mIndex;
}
return ssize_t(0xFFFF0000 | mIndex);
}
sp<LayerBaseClient::Surface> LayerBaseClient::getSurface() sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
{ {
sp<Surface> s; sp<Surface> s;
@@ -533,7 +516,7 @@ sp<LayerBaseClient::Surface> LayerBaseClient::getSurface()
sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const sp<LayerBaseClient::Surface> LayerBaseClient::createSurface() const
{ {
return new Surface(mFlinger, clientIndex(), mIdentity, return new Surface(mFlinger, mIdentity,
const_cast<LayerBaseClient *>(this)); const_cast<LayerBaseClient *>(this));
} }
@@ -544,10 +527,9 @@ void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
sp<Client> client(this->client.promote()); sp<Client> client(this->client.promote());
snprintf(buffer, SIZE, snprintf(buffer, SIZE,
" name=%s\n" " name=%s\n"
" id=0x%08x, client=0x%08x, identity=%u\n", " client=%p, identity=%u\n",
getName().string(), getName().string(),
clientIndex(), client.get() ? client->cid : 0, client.get(), getIdentity());
getIdentity());
result.append(buffer); result.append(buffer);
} }
@@ -556,9 +538,9 @@ void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const
LayerBaseClient::Surface::Surface( LayerBaseClient::Surface::Surface(
const sp<SurfaceFlinger>& flinger, const sp<SurfaceFlinger>& flinger,
SurfaceID id, int identity, int identity,
const sp<LayerBaseClient>& owner) const sp<LayerBaseClient>& owner)
: mFlinger(flinger), mToken(id), mIdentity(identity), mOwner(owner) : mFlinger(flinger), mIdentity(identity), mOwner(owner)
{ {
} }

View File

@@ -101,7 +101,6 @@ public:
void invalidate(); void invalidate();
virtual const char* getTypeId() const { return "LayerBase"; } virtual const char* getTypeId() const { return "LayerBase"; }
virtual ssize_t serverIndex() const { return -1; }
/** /**
* draw - performs some global clipping optimizations * draw - performs some global clipping optimizations
@@ -269,30 +268,24 @@ class LayerBaseClient : public LayerBase
public: public:
class Surface; class Surface;
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerBaseClient();
virtual void onFirstRef();
const wp<Client> client; const wp<Client> client;
inline uint32_t getIdentity() const { return mIdentity; } LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
inline int32_t clientIndex() const { return mIndex; } const sp<Client>& client);
virtual ~LayerBaseClient();
sp<Surface> getSurface(); sp<Surface> getSurface();
virtual sp<Surface> createSurface() const; virtual sp<Surface> createSurface() const;
virtual ssize_t serverIndex() const;
virtual const char* getTypeId() const { return "LayerBaseClient"; } virtual const char* getTypeId() const { return "LayerBaseClient"; }
class Surface : public BnSurface uint32_t getIdentity() const { return mIdentity; }
{
class Surface : public BnSurface {
public: public:
int32_t getToken() const { return mToken; }
int32_t getIdentity() const { return mIdentity; } int32_t getIdentity() const { return mIdentity; }
protected: protected:
Surface(const sp<SurfaceFlinger>& flinger, Surface(const sp<SurfaceFlinger>& flinger, int identity,
SurfaceID id, int identity,
const sp<LayerBaseClient>& owner); const sp<LayerBaseClient>& owner);
virtual ~Surface(); virtual ~Surface();
virtual status_t onTransact(uint32_t code, const Parcel& data, virtual status_t onTransact(uint32_t code, const Parcel& data,
@@ -313,7 +306,6 @@ public:
protected: protected:
friend class LayerBaseClient; friend class LayerBaseClient;
sp<SurfaceFlinger> mFlinger; sp<SurfaceFlinger> mFlinger;
int32_t mToken;
int32_t mIdentity; int32_t mIdentity;
wp<LayerBaseClient> mOwner; wp<LayerBaseClient> mOwner;
}; };
@@ -324,12 +316,16 @@ protected:
virtual void dump(String8& result, char* scratch, size_t size) const; virtual void dump(String8& result, char* scratch, size_t size) const;
private: private:
int32_t mIndex;
mutable Mutex mLock; mutable Mutex mLock;
mutable wp<Surface> mClientSurface; mutable wp<Surface> mClientSurface;
// only read // only read
const uint32_t mIdentity; const uint32_t mIdentity;
static int32_t sIdentity; static int32_t sIdentity;
// TODO: get rid of this
public:
virtual void setToken(int32_t token) { }
virtual int32_t getToken() const { return -1; }
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -34,8 +34,8 @@ namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i) const sp<Client>& client)
: LayerBaseClient(flinger, display, client, i), mCacheDirty(true), : LayerBaseClient(flinger, display, client), mCacheDirty(true),
mRefreshCache(true), mCacheAge(0), mTextureName(-1U), mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
mWidthScale(1.0f), mHeightScale(1.0f), mWidthScale(1.0f), mHeightScale(1.0f),
mBlurFormat(GGL_PIXEL_FORMAT_RGB_565) mBlurFormat(GGL_PIXEL_FORMAT_RGB_565)

View File

@@ -32,7 +32,7 @@ class LayerBlur : public LayerBaseClient
{ {
public: public:
LayerBlur(SurfaceFlinger* flinger, DisplayID display, LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i); const sp<Client>& client);
virtual ~LayerBlur(); virtual ~LayerBlur();
virtual void onDraw(const Region& clip) const; virtual void onDraw(const Region& clip) const;

View File

@@ -44,8 +44,8 @@ gralloc_module_t const* LayerBuffer::sGrallocModule = 0;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display, LayerBuffer::LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i) const sp<Client>& client)
: LayerBaseClient(flinger, display, client, i), : LayerBaseClient(flinger, display, client),
mNeedsBlending(false), mBlitEngine(0) mNeedsBlending(false), mBlitEngine(0)
{ {
} }
@@ -60,8 +60,7 @@ LayerBuffer::~LayerBuffer()
void LayerBuffer::onFirstRef() void LayerBuffer::onFirstRef()
{ {
LayerBaseClient::onFirstRef(); LayerBaseClient::onFirstRef();
mSurface = new SurfaceLayerBuffer(mFlinger, clientIndex(), mSurface = new SurfaceLayerBuffer(mFlinger, this);
const_cast<LayerBuffer *>(this));
hw_module_t const* module = (hw_module_t const*)sGrallocModule; hw_module_t const* module = (hw_module_t const*)sGrallocModule;
if (!module) { if (!module) {
@@ -204,9 +203,9 @@ sp<LayerBuffer::Source> LayerBuffer::clearSource() {
// LayerBuffer::SurfaceLayerBuffer // LayerBuffer::SurfaceLayerBuffer
// ============================================================================ // ============================================================================
LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger, LayerBuffer::SurfaceLayerBuffer::SurfaceLayerBuffer(
SurfaceID id, const sp<LayerBuffer>& owner) const sp<SurfaceFlinger>& flinger, const sp<LayerBuffer>& owner)
: LayerBaseClient::Surface(flinger, id, owner->getIdentity(), owner) : LayerBaseClient::Surface(flinger, owner->getIdentity(), owner)
{ {
} }

View File

@@ -53,7 +53,7 @@ class LayerBuffer : public LayerBaseClient
public: public:
LayerBuffer(SurfaceFlinger* flinger, DisplayID display, LayerBuffer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i); const sp<Client>& client);
virtual ~LayerBuffer(); virtual ~LayerBuffer();
virtual void onFirstRef(); virtual void onFirstRef();
@@ -189,7 +189,7 @@ private:
{ {
public: public:
SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger, SurfaceLayerBuffer(const sp<SurfaceFlinger>& flinger,
SurfaceID id, const sp<LayerBuffer>& owner); const sp<LayerBuffer>& owner);
virtual ~SurfaceLayerBuffer(); virtual ~SurfaceLayerBuffer();
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);

View File

@@ -39,8 +39,8 @@ int32_t LayerDim::sHeight;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display, LayerDim::LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i) const sp<Client>& client)
: LayerBaseClient(flinger, display, client, i) : LayerBaseClient(flinger, display, client)
{ {
} }

View File

@@ -38,7 +38,7 @@ class LayerDim : public LayerBaseClient
static int32_t sHeight; static int32_t sHeight;
public: public:
LayerDim(SurfaceFlinger* flinger, DisplayID display, LayerDim(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i); const sp<Client>& client);
virtual ~LayerDim(); virtual ~LayerDim();
virtual void onDraw(const Region& clip) const; virtual void onDraw(const Region& clip) const;

View File

@@ -227,54 +227,15 @@ sp<IMemoryHeap> SurfaceFlinger::getCblk() const
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
{ {
Mutex::Autolock _l(mStateLock); sp<ISurfaceComposerClient> bclient;
uint32_t token = mTokens.acquire(); sp<Client> client(new Client(this));
status_t err = client->initCheck();
sp<Client> client = new Client(token, this); if (err == NO_ERROR) {
if (client->ctrlblk == 0) { bclient = client;
mTokens.release(token);
return 0;
} }
status_t err = mClientsMap.add(token, client);
if (err < 0) {
mTokens.release(token);
return 0;
}
sp<BClient> bclient =
new BClient(this, token, client->getControlBlockMemory());
return bclient; return bclient;
} }
void SurfaceFlinger::destroyConnection(ClientID cid)
{
Mutex::Autolock _l(mStateLock);
sp<Client> client = mClientsMap.valueFor(cid);
if (client != 0) {
// free all the layers this client owns
Vector< wp<LayerBaseClient> > layers(client->getLayers());
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
sp<LayerBaseClient> layer(layers[i].promote());
if (layer != 0) {
purgatorizeLayer_l(layer);
}
}
// the resources associated with this client will be freed
// during the next transaction, after these surfaces have been
// properly removed from the screen
// remove this client from our ClientID->Client mapping.
mClientsMap.removeItem(cid);
// and add it to the list of disconnected clients
mDisconnectedClients.add(client);
// request a transaction
setTransactionFlags(eTransactionNeeded);
}
}
const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
{ {
LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy); LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
@@ -665,10 +626,6 @@ void SurfaceFlinger::handleTransactionLocked(
} }
} }
} }
// get rid of all resources we don't need anymore
// (layers and clients)
free_resources_l();
} }
commitTransaction(); commitTransaction();
@@ -1071,6 +1028,27 @@ status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
return NO_ERROR; return NO_ERROR;
} }
status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
{
ssize_t i = mCurrentState.layersSortedByZ.add(
layer, &LayerBase::compareCurrentStateZ);
return (i < 0) ? status_t(i) : status_t(NO_ERROR);
}
ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
const sp<LayerBaseClient>& lbc)
{
Mutex::Autolock _l(mStateLock);
// attach this layer to the client
ssize_t name = client->attachLayer(lbc);
// add this layer to the current state list
addLayer_l(lbc);
return name;
}
status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
{ {
Mutex::Autolock _l(mStateLock); Mutex::Autolock _l(mStateLock);
@@ -1080,35 +1058,11 @@ status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
return err; return err;
} }
status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
{
layer->forceVisibilityTransaction();
setTransactionFlags(eTraversalNeeded);
return NO_ERROR;
}
status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
{
ssize_t i = mCurrentState.layersSortedByZ.add(
layer, &LayerBase::compareCurrentStateZ);
return (i < 0) ? status_t(i) : status_t(NO_ERROR);
}
status_t SurfaceFlinger::addClientLayer_l(const sp<LayerBaseClient>& lbc)
{
ssize_t serverIndex = lbc->serverIndex();
return mLayerMap.add(serverIndex, lbc);
}
status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
{ {
ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
if (index >= 0) { if (index >= 0) {
mLayersRemoved = true; mLayersRemoved = true;
ssize_t serverIndex = layerBase->serverIndex();
if (serverIndex >= 0) {
mLayerMap.removeItem(serverIndex);
}
return NO_ERROR; return NO_ERROR;
} }
return status_t(index); return status_t(index);
@@ -1123,22 +1077,16 @@ status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
// it's possible that we don't find a layer, because it might // it's possible that we don't find a layer, because it might
// have been destroyed already -- this is not technically an error // have been destroyed already -- this is not technically an error
// from the user because there is a race between BClient::destroySurface(), // from the user because there is a race between Client::destroySurface(),
// ~BClient() and ~ISurface(). // ~Client() and ~ISurface().
return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err; return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
} }
status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
void SurfaceFlinger::free_resources_l()
{ {
// free resources associated with disconnected clients layer->forceVisibilityTransaction();
Vector< sp<Client> >& disconnectedClients(mDisconnectedClients); setTransactionFlags(eTraversalNeeded);
const size_t count = disconnectedClients.size(); return NO_ERROR;
for (size_t i=0 ; i<count ; i++) {
sp<Client> client = disconnectedClients[i];
mTokens.release(client->cid);
}
disconnectedClients.clear();
} }
uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
@@ -1229,7 +1177,7 @@ int SurfaceFlinger::setOrientation(DisplayID dpy,
return orientation; return orientation;
} }
sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid, sp<ISurface> SurfaceFlinger::createSurface(const sp<Client>& client, int pid,
const String8& name, ISurfaceComposerClient::surface_data_t* params, const String8& name, ISurfaceComposerClient::surface_data_t* params,
DisplayID d, uint32_t w, uint32_t h, PixelFormat format, DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags) uint32_t flags)
@@ -1243,57 +1191,44 @@ sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
return surfaceHandle; return surfaceHandle;
} }
Mutex::Autolock _l(mStateLock);
sp<Client> client = mClientsMap.valueFor(clientId);
if (UNLIKELY(client == 0)) {
LOGE("createSurface() failed, client not found (id=%d)", clientId);
return surfaceHandle;
}
//LOGD("createSurface for pid %d (%d x %d)", pid, w, h); //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
int32_t id = client->generateId(pid);
if (uint32_t(id) >= SharedBufferStack::NUM_LAYERS_MAX) {
LOGE("createSurface() failed, generateId = %d", id);
return surfaceHandle;
}
switch (flags & eFXSurfaceMask) { switch (flags & eFXSurfaceMask) {
case eFXSurfaceNormal: case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) { if (UNLIKELY(flags & ePushBuffers)) {
layer = createPushBuffersSurfaceLocked(client, d, id, layer = createPushBuffersSurface(client, d, w, h, flags);
w, h, flags);
} else { } else {
layer = createNormalSurfaceLocked(client, d, id, layer = createNormalSurface(client, d, w, h, flags, format);
w, h, flags, format);
} }
break; break;
case eFXSurfaceBlur: case eFXSurfaceBlur:
layer = createBlurSurfaceLocked(client, d, id, w, h, flags); layer = createBlurSurface(client, d, w, h, flags);
break; break;
case eFXSurfaceDim: case eFXSurfaceDim:
layer = createDimSurfaceLocked(client, d, id, w, h, flags); layer = createDimSurface(client, d, w, h, flags);
break; break;
} }
if (layer != 0) { if (layer != 0) {
layer->initStates(w, h, flags);
layer->setName(name); layer->setName(name);
setTransactionFlags(eTransactionNeeded); ssize_t token = addClientLayer(client, layer);
surfaceHandle = layer->getSurface(); surfaceHandle = layer->getSurface();
if (surfaceHandle != 0) { if (surfaceHandle != 0) {
params->token = surfaceHandle->getToken(); params->token = token;
params->identity = surfaceHandle->getIdentity(); params->identity = surfaceHandle->getIdentity();
params->width = w; params->width = w;
params->height = h; params->height = h;
params->format = format; params->format = format;
} }
setTransactionFlags(eTransactionNeeded);
} }
return surfaceHandle; return surfaceHandle;
} }
sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked( sp<LayerBaseClient> SurfaceFlinger::createNormalSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags, uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format) PixelFormat& format)
{ {
// initialize the surfaces // initialize the surfaces
@@ -1307,53 +1242,43 @@ sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
break; break;
} }
sp<Layer> layer = new Layer(this, display, client, id); sp<Layer> layer = new Layer(this, display, client);
status_t err = layer->setBuffers(w, h, format, flags); status_t err = layer->setBuffers(w, h, format, flags);
if (LIKELY(err == NO_ERROR)) { if (LIKELY(err != NO_ERROR)) {
layer->initStates(w, h, flags);
addLayer_l(layer);
addClientLayer_l(layer);
} else {
LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err)); LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
layer.clear(); layer.clear();
} }
return layer; return layer;
} }
sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked( sp<LayerBaseClient> SurfaceFlinger::createBlurSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags) uint32_t w, uint32_t h, uint32_t flags)
{ {
sp<LayerBlur> layer = new LayerBlur(this, display, client, id); sp<LayerBlur> layer = new LayerBlur(this, display, client);
layer->initStates(w, h, flags); layer->initStates(w, h, flags);
addLayer_l(layer);
addClientLayer_l(layer);
return layer; return layer;
} }
sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked( sp<LayerBaseClient> SurfaceFlinger::createDimSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags) uint32_t w, uint32_t h, uint32_t flags)
{ {
sp<LayerDim> layer = new LayerDim(this, display, client, id); sp<LayerDim> layer = new LayerDim(this, display, client);
layer->initStates(w, h, flags); layer->initStates(w, h, flags);
addLayer_l(layer);
addClientLayer_l(layer);
return layer; return layer;
} }
sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked( sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags) uint32_t w, uint32_t h, uint32_t flags)
{ {
sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id); sp<LayerBuffer> layer = new LayerBuffer(this, display, client);
layer->initStates(w, h, flags); layer->initStates(w, h, flags);
addLayer_l(layer);
addClientLayer_l(layer);
return layer; return layer;
} }
status_t SurfaceFlinger::removeSurface(SurfaceID index) status_t SurfaceFlinger::removeSurface(const sp<Client>& client, SurfaceID sid)
{ {
/* /*
* called by the window manager, when a surface should be marked for * called by the window manager, when a surface should be marked for
@@ -1366,7 +1291,7 @@ status_t SurfaceFlinger::removeSurface(SurfaceID index)
status_t err = NAME_NOT_FOUND; status_t err = NAME_NOT_FOUND;
Mutex::Autolock _l(mStateLock); Mutex::Autolock _l(mStateLock);
sp<LayerBaseClient> layer = getLayerUser_l(index); sp<LayerBaseClient> layer = client->getLayerUser(sid);
if (layer != 0) { if (layer != 0) {
err = purgatorizeLayer_l(layer); err = purgatorizeLayer_l(layer);
if (err == NO_ERROR) { if (err == NO_ERROR) {
@@ -1411,16 +1336,15 @@ status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
} }
status_t SurfaceFlinger::setClientState( status_t SurfaceFlinger::setClientState(
ClientID cid, const sp<Client>& client,
int32_t count, int32_t count,
const layer_state_t* states) const layer_state_t* states)
{ {
Mutex::Autolock _l(mStateLock); Mutex::Autolock _l(mStateLock);
uint32_t flags = 0; uint32_t flags = 0;
cid <<= 16;
for (int i=0 ; i<count ; i++) { for (int i=0 ; i<count ; i++) {
const layer_state_t& s = states[i]; const layer_state_t& s(states[i]);
sp<LayerBaseClient> layer(getLayerUser_l(s.surface | cid)); sp<LayerBaseClient> layer(client->getLayerUser(s.surface));
if (layer != 0) { if (layer != 0) {
const uint32_t what = s.what; const uint32_t what = s.what;
if (what & ePositionChanged) { if (what & ePositionChanged) {
@@ -1466,12 +1390,6 @@ status_t SurfaceFlinger::setClientState(
return NO_ERROR; return NO_ERROR;
} }
sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
{
sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
return layer;
}
void SurfaceFlinger::screenReleased(int dpy) void SurfaceFlinger::screenReleased(int dpy)
{ {
// this may be called by a signal handler, we can't do too much in here // this may be called by a signal handler, we can't do too much in here
@@ -1557,8 +1475,6 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
result.append(buffer); result.append(buffer);
} }
snprintf(buffer, SIZE, " client count: %d\n", mClientsMap.size());
result.append(buffer);
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get()); const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
alloc.dump(result); alloc.dump(result);
@@ -1655,8 +1571,8 @@ status_t SurfaceFlinger::onTransact(
#pragma mark - #pragma mark -
#endif #endif
Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger) Client::Client(const sp<SurfaceFlinger>& flinger)
: ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger) : ctrlblk(0), mBitmap(0), mFlinger(flinger)
{ {
const int pgsize = getpagesize(); const int pgsize = getpagesize();
const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1)); const int cblksize = ((sizeof(SharedClient)+(pgsize-1))&~(pgsize-1));
@@ -1668,96 +1584,87 @@ Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
if (ctrlblk) { // construct the shared structure in-place. if (ctrlblk) { // construct the shared structure in-place.
new(ctrlblk) SharedClient; new(ctrlblk) SharedClient;
} }
} }
Client::~Client() { Client::~Client()
{
if (ctrlblk) { if (ctrlblk) {
ctrlblk->~SharedClient(); // destroy our shared-structure. ctrlblk->~SharedClient(); // destroy our shared-structure.
} }
const size_t count = mLayers.size();
for (size_t i=0 ; i<count ; i++) {
sp<LayerBaseClient> layer(mLayers.valueAt(i).promote());
if (layer != 0) {
mFlinger->removeLayer(layer);
}
}
} }
int32_t Client::generateId(int pid) status_t Client::initCheck() const {
return ctrlblk == 0 ? NO_INIT : NO_ERROR;
}
ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
{ {
const uint32_t i = clz( ~mBitmap ); // TODO: get rid of this
if (i >= SharedBufferStack::NUM_LAYERS_MAX) { int32_t name = 0;
while (mBitmap & (1LU<<name)) {
name++;
if (name >= 31)
return NO_MEMORY; return NO_MEMORY;
} }
mPid = pid; mBitmap |= 1LU<<name;
mInUse.add(uint8_t(i)); layer->setToken(name);
mBitmap |= 1<<(31-i); mLayers.add(name, layer);
return i; return name;
} }
status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id) void Client::free(LayerBaseClient const* layer)
{ {
ssize_t idx = mInUse.indexOf(id); // TODO: get rid of this
if (idx < 0) int32_t name = layer->getToken();
return NAME_NOT_FOUND; if (name >= 0) {
return mLayers.insertAt(layer, idx); mBitmap &= ~(1LU<<name);
} }
void Client::free(int32_t id) // we do a linear search here, because this doesn't happen often
{ const size_t count = mLayers.size();
ssize_t idx = mInUse.remove(uint8_t(id)); for (size_t i=0 ; i<count ; i++) {
if (idx >= 0) { if (mLayers.valueAt(i) == layer) {
mBitmap &= ~(1<<(31-id)); mLayers.removeItemsAt(i, 1);
mLayers.removeItemsAt(idx); break;
} }
} }
bool Client::isValid(int32_t i) const {
return (uint32_t(i)<SharedBufferStack::NUM_LAYERS_MAX) &&
(mBitmap & (1<<(31-i)));
} }
sp<LayerBaseClient> Client::getLayerUser(int32_t i) const { sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
sp<LayerBaseClient> lbc; sp<LayerBaseClient> lbc;
ssize_t idx = mInUse.indexOf(uint8_t(i)); const wp<LayerBaseClient>& layer(mLayers.valueFor(i));
if (idx >= 0) { if (layer != 0) {
lbc = mLayers[idx].promote(); lbc = layer.promote();
LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx)); LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
} }
return lbc; return lbc;
} }
// --------------------------------------------------------------------------- sp<IMemoryHeap> Client::getControlBlock() const {
#if 0 return mCblkHeap;
#pragma mark -
#endif
BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemoryHeap>& cblk)
: mId(cid), mFlinger(flinger), mCblk(cblk)
{
} }
sp<ISurface> Client::createSurface(
BClient::~BClient() { ISurfaceComposerClient::surface_data_t* params,
// destroy all resources attached to this client int pid, const String8& name,
mFlinger->destroyConnection(mId);
}
sp<IMemoryHeap> BClient::getControlBlock() const {
return mCblk;
}
sp<ISurface> BClient::createSurface(
ISurfaceComposerClient::surface_data_t* params, int pid,
const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format, DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags) uint32_t flags)
{ {
return mFlinger->createSurface(mId, pid, name, params, display, w, h, return mFlinger->createSurface(this, pid, name, params,
format, flags); display, w, h, format, flags);
} }
status_t Client::destroySurface(SurfaceID sid) {
status_t BClient::destroySurface(SurfaceID sid) return mFlinger->removeSurface(this, sid);
{
sid |= (mId << 16); // add the client-part to id
return mFlinger->removeSurface(sid);
} }
status_t Client::setState(int32_t count, const layer_state_t* states) {
status_t BClient::setState(int32_t count, const layer_state_t* states) return mFlinger->setClientState(this, count, states);
{
return mFlinger->setClientState(mId, count, states);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -36,7 +36,6 @@
#include "Barrier.h" #include "Barrier.h"
#include "Layer.h" #include "Layer.h"
#include "Tokenizer.h"
#include "MessageQueue.h" #include "MessageQueue.h"
@@ -48,52 +47,46 @@ namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class Client; class Client;
class BClient;
class DisplayHardware; class DisplayHardware;
class FreezeLock; class FreezeLock;
class Layer; class Layer;
class LayerBuffer; class LayerBuffer;
typedef int32_t ClientID;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
class Client : public RefBase class Client : public BnSurfaceComposerClient
{ {
public: public:
Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
~Client();
int32_t generateId(int pid);
void free(int32_t id);
status_t bindLayer(const sp<LayerBaseClient>& layer, int32_t id);
inline bool isValid(int32_t i) const;
sp<LayerBaseClient> getLayerUser(int32_t i) const;
const Vector< wp<LayerBaseClient> >& getLayers() const {
return mLayers;
}
const sp<IMemoryHeap>& getControlBlockMemory() const {
return mCblkHeap;
}
// pointer to this client's control block // pointer to this client's control block
SharedClient* ctrlblk; SharedClient* ctrlblk;
ClientID cid;
public:
Client(const sp<SurfaceFlinger>& flinger);
~Client();
status_t initCheck() const;
// protected by SurfaceFlinger::mStateLock
ssize_t attachLayer(const sp<LayerBaseClient>& layer);
sp<LayerBaseClient> getLayerUser(int32_t i) const;
void free(LayerBaseClient const* layer);
private: private:
int getClientPid() const { return mPid; }
int mPid; // ISurfaceComposerClient interface
virtual sp<IMemoryHeap> getControlBlock() const;
virtual sp<ISurface> createSurface(
surface_data_t* params, int pid, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
uint32_t mBitmap; uint32_t mBitmap;
SortedVector<uint8_t> mInUse; DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
Vector< wp<LayerBaseClient> > mLayers;
sp<IMemoryHeap> mCblkHeap; sp<IMemoryHeap> mCblkHeap;
sp<SurfaceFlinger> mFlinger; sp<SurfaceFlinger> mFlinger;
}; };
@@ -179,7 +172,7 @@ public:
status_t invalidateLayerVisibility(const sp<LayerBase>& layer); status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
private: private:
friend class BClient; friend class Client;
friend class LayerBase; friend class LayerBase;
friend class LayerBuffer; friend class LayerBuffer;
friend class LayerBaseClient; friend class LayerBaseClient;
@@ -188,31 +181,33 @@ private:
friend class LayerBlur; friend class LayerBlur;
friend class LayerDim; friend class LayerDim;
sp<ISurface> createSurface(ClientID client, int pid, const String8& name, sp<ISurface> createSurface(const sp<Client>& client,
int pid, const String8& name,
ISurfaceComposerClient::surface_data_t* params, ISurfaceComposerClient::surface_data_t* params,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format, DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags); uint32_t flags);
sp<LayerBaseClient> createNormalSurfaceLocked( sp<LayerBaseClient> createNormalSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags, uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format); PixelFormat& format);
sp<LayerBaseClient> createBlurSurfaceLocked( sp<LayerBaseClient> createBlurSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags); uint32_t w, uint32_t h, uint32_t flags);
sp<LayerBaseClient> createDimSurfaceLocked( sp<LayerBaseClient> createDimSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags); uint32_t w, uint32_t h, uint32_t flags);
sp<LayerBaseClient> createPushBuffersSurfaceLocked( sp<LayerBaseClient> createPushBuffersSurface(
const sp<Client>& client, DisplayID display, const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags); uint32_t w, uint32_t h, uint32_t flags);
status_t removeSurface(SurfaceID surface_id); status_t removeSurface(const sp<Client>& client, SurfaceID sid);
status_t destroySurface(const sp<LayerBaseClient>& layer); status_t destroySurface(const sp<LayerBaseClient>& layer);
status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states); status_t setClientState(const sp<Client>& client,
int32_t count, const layer_state_t* states);
class LayerVector { class LayerVector {
@@ -275,13 +270,11 @@ private:
void unlockClients(); void unlockClients();
void destroyConnection(ClientID cid); ssize_t addClientLayer(const sp<Client>& client,
sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const; const sp<LayerBaseClient>& lbc);
status_t addLayer_l(const sp<LayerBase>& layer); status_t addLayer_l(const sp<LayerBase>& layer);
status_t addClientLayer_l(const sp<LayerBaseClient>& lbc);
status_t removeLayer_l(const sp<LayerBase>& layer); status_t removeLayer_l(const sp<LayerBase>& layer);
status_t purgatorizeLayer_l(const sp<LayerBase>& layer); status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
void free_resources_l();
uint32_t getTransactionFlags(uint32_t flags); uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags);
@@ -326,12 +319,8 @@ private:
bool mResizeTransationPending; bool mResizeTransationPending;
// protected by mStateLock (but we could use another lock) // protected by mStateLock (but we could use another lock)
Tokenizer mTokens;
DefaultKeyedVector<ClientID, sp<Client> > mClientsMap;
DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap;
GraphicPlane mGraphicPlanes[1]; GraphicPlane mGraphicPlanes[1];
bool mLayersRemoved; bool mLayersRemoved;
Vector< sp<Client> > mDisconnectedClients;
// constant members (no synchronization needed for access) // constant members (no synchronization needed for access)
sp<IMemoryHeap> mServerHeap; sp<IMemoryHeap> mServerHeap;
@@ -391,32 +380,6 @@ public:
} }
}; };
// ---------------------------------------------------------------------------
class BClient : public BnSurfaceComposerClient
{
public:
BClient(SurfaceFlinger *flinger, ClientID cid,
const sp<IMemoryHeap>& cblk);
~BClient();
// ISurfaceComposerClient interface
virtual sp<IMemoryHeap> getControlBlock() const;
virtual sp<ISurface> createSurface(
surface_data_t* params, int pid, const String8& name,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
private:
ClientID mId;
SurfaceFlinger* mFlinger;
sp<IMemoryHeap> mCblk;
};
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
}; // namespace android }; // namespace android

View File

@@ -1,173 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "Tokenizer.h"
// ----------------------------------------------------------------------------
namespace android {
ANDROID_BASIC_TYPES_TRAITS(Tokenizer::run_t)
Tokenizer::Tokenizer()
{
}
Tokenizer::Tokenizer(const Tokenizer& other)
: mRanges(other.mRanges)
{
}
Tokenizer::~Tokenizer()
{
}
uint32_t Tokenizer::acquire()
{
if (!mRanges.size() || mRanges[0].first) {
_insertTokenAt(0,0);
return 0;
}
// just extend the first run
const run_t& run = mRanges[0];
uint32_t token = run.first + run.length;
_insertTokenAt(token, 1);
return token;
}
bool Tokenizer::isAcquired(uint32_t token) const
{
return (_indexOrderOf(token) >= 0);
}
status_t Tokenizer::reserve(uint32_t token)
{
size_t o;
const ssize_t i = _indexOrderOf(token, &o);
if (i >= 0) {
return BAD_VALUE; // this token is already taken
}
ssize_t err = _insertTokenAt(token, o);
return (err<0) ? err : status_t(NO_ERROR);
}
status_t Tokenizer::release(uint32_t token)
{
const ssize_t i = _indexOrderOf(token);
if (i >= 0) {
const run_t& run = mRanges[i];
if ((token >= run.first) && (token < run.first+run.length)) {
// token in this range, we need to split
run_t& run = mRanges.editItemAt(i);
if ((token == run.first) || (token == run.first+run.length-1)) {
if (token == run.first) {
run.first += 1;
}
run.length -= 1;
if (run.length == 0) {
// XXX: should we systematically remove a run that's empty?
mRanges.removeItemsAt(i);
}
} else {
// split the run
run_t new_run;
new_run.first = token+1;
new_run.length = run.first+run.length - new_run.first;
run.length = token - run.first;
mRanges.insertAt(new_run, i+1);
}
return NO_ERROR;
}
}
return NAME_NOT_FOUND;
}
ssize_t Tokenizer::_indexOrderOf(uint32_t token, size_t* order) const
{
// binary search
ssize_t err = NAME_NOT_FOUND;
ssize_t l = 0;
ssize_t h = mRanges.size()-1;
ssize_t mid;
const run_t* a = mRanges.array();
while (l <= h) {
mid = l + (h - l)/2;
const run_t* const curr = a + mid;
int c = 0;
if (token < curr->first) c = 1;
else if (token >= curr->first+curr->length) c = -1;
if (c == 0) {
err = l = mid;
break;
} else if (c < 0) {
l = mid + 1;
} else {
h = mid - 1;
}
}
if (order) *order = l;
return err;
}
ssize_t Tokenizer::_insertTokenAt(uint32_t token, size_t index)
{
const size_t c = mRanges.size();
if (index >= 1) {
// do we need to merge with the previous run?
run_t& p = mRanges.editItemAt(index-1);
if (p.first+p.length == token) {
p.length += 1;
if (index < c) {
const run_t& n = mRanges[index];
if (token+1 == n.first) {
p.length += n.length;
mRanges.removeItemsAt(index);
}
}
return index;
}
}
if (index < c) {
// do we need to merge with the next run?
run_t& n = mRanges.editItemAt(index);
if (token+1 == n.first) {
n.first -= 1;
n.length += 1;
return index;
}
}
return mRanges.insertAt(run_t(token,1), index);
}
void Tokenizer::dump() const
{
const run_t* ranges = mRanges.array();
const size_t c = mRanges.size();
printf("Tokenizer (%p, size = %d)\n", this, int(c));
for (size_t i=0 ; i<c ; i++) {
printf("%u: (%u, %u)\n", i,
uint32_t(ranges[i].first), uint32_t(ranges[i].length));
}
}
}; // namespace android

View File

@@ -1,57 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_TOKENIZER_H
#define ANDROID_TOKENIZER_H
#include <utils/Vector.h>
#include <utils/Errors.h>
// ----------------------------------------------------------------------------
namespace android {
class Tokenizer
{
public:
Tokenizer();
Tokenizer(const Tokenizer& other);
~Tokenizer();
uint32_t acquire();
status_t reserve(uint32_t token);
status_t release(uint32_t token);
bool isAcquired(uint32_t token) const;
void dump() const;
struct run_t {
run_t() {};
run_t(uint32_t f, uint32_t l) : first(f), length(l) {}
uint32_t first;
uint32_t length;
};
private:
ssize_t _indexOrderOf(uint32_t token, size_t* order=0) const;
ssize_t _insertTokenAt(uint32_t token, size_t index);
Vector<run_t> mRanges;
};
}; // namespace android
// ----------------------------------------------------------------------------
#endif // ANDROID_TOKENIZER_H