summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2010-05-21 17:24:35 -0700
committerMathias Agopian <mathias@google.com>2010-05-24 18:26:01 -0700
commita138f89c5e78b7e8994823e97d6e860869762837 (patch)
tree9d11e5f9ee406798070a5cb335390147ae1dffa5 /libs
parenta0b3f1d2eb796eb90a7576c13890ab8df8516d9d (diff)
downloadframeworks_native-a138f89c5e78b7e8994823e97d6e860869762837.zip
frameworks_native-a138f89c5e78b7e8994823e97d6e860869762837.tar.gz
frameworks_native-a138f89c5e78b7e8994823e97d6e860869762837.tar.bz2
added the notion of fixed-size buffers
the new native_window_set_buffers_geometry allows to specify a size and format for all buffers to be dequeued. the buffer will be scalled to the window's size. Change-Id: I2c378b85c88d29cdd827a5f319d5c704d79ba381
Diffstat (limited to 'libs')
-rw-r--r--libs/surfaceflinger/Layer.cpp113
-rw-r--r--libs/surfaceflinger/Layer.h13
-rw-r--r--libs/surfaceflinger/LayerBase.cpp3
-rw-r--r--libs/surfaceflinger/LayerBase.h3
-rw-r--r--libs/surfaceflinger_client/ISurface.cpp13
-rw-r--r--libs/surfaceflinger_client/SharedBufferStack.cpp16
-rw-r--r--libs/surfaceflinger_client/Surface.cpp141
7 files changed, 216 insertions, 86 deletions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 621b7e3..84584aa 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -55,7 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
mNeedsBlending(true),
mNeedsDithering(false),
mTextureManager(mFlags),
- mBufferManager(mTextureManager)
+ mBufferManager(mTextureManager),
+ mWidth(0), mHeight(0), mFixedSize(false)
{
// no OpenGL operation is possible here, since we might not be
// in the OpenGL thread.
@@ -227,10 +228,18 @@ status_t Layer::setBufferCount(int bufferCount)
return err;
}
-sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
+sp<GraphicBuffer> Layer::requestBuffer(int index,
+ uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
+ uint32_t usage)
{
sp<GraphicBuffer> buffer;
+ if ((reqWidth | reqHeight | reqFormat) < 0)
+ return buffer;
+
+ if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
+ return buffer;
+
// this ensures our client doesn't go away while we're accessing
// the shared area.
sp<Client> ourClient(client.promote());
@@ -256,23 +265,33 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
return buffer;
}
- uint32_t w, h;
+ uint32_t w, h, f;
{ // scope for the lock
Mutex::Autolock _l(mLock);
- w = mWidth;
- h = mHeight;
+ const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
+ const bool formatChanged = mReqFormat != reqFormat;
+ mReqWidth = reqWidth;
+ mReqHeight = reqHeight;
+ mReqFormat = reqFormat;
+ mFixedSize = reqWidth && reqHeight;
+ w = reqWidth ? reqWidth : mWidth;
+ h = reqHeight ? reqHeight : mHeight;
+ f = reqFormat ? reqFormat : mFormat;
buffer = mBufferManager.detachBuffer(index);
+ if (fixedSizeChanged || formatChanged) {
+ lcblk->reallocateAllExcept(index);
+ }
}
const uint32_t effectiveUsage = getEffectiveUsage(usage);
if (buffer!=0 && buffer->getStrongCount() == 1) {
- err = buffer->reallocate(w, h, mFormat, effectiveUsage);
+ err = buffer->reallocate(w, h, f, effectiveUsage);
} else {
// here we have to reallocate a new buffer because we could have a
// client in our process with a reference to it (eg: status bar),
// and we can't release the handle under its feet.
buffer.clear();
- buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
+ buffer = new GraphicBuffer(w, h, f, effectiveUsage);
err = buffer->initCheck();
}
@@ -288,12 +307,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
if (err == NO_ERROR && buffer->handle != 0) {
Mutex::Autolock _l(mLock);
- if (mWidth && mHeight) {
- mBufferManager.attachBuffer(index, buffer);
- } else {
- // oops we got killed while we were allocating the buffer
- buffer.clear();
- }
+ mBufferManager.attachBuffer(index, buffer);
}
return buffer;
}
@@ -330,39 +344,46 @@ uint32_t Layer::doTransaction(uint32_t flags)
const Layer::State& front(drawingState());
const Layer::State& temp(currentState());
- if ((front.requested_w != temp.requested_w) ||
- (front.requested_h != temp.requested_h)) {
+ const bool sizeChanged = (front.requested_w != temp.requested_w) ||
+ (front.requested_h != temp.requested_h);
+
+ if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
- "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
- this,
- int(temp.requested_w), int(temp.requested_h),
- int(front.requested_w), int(front.requested_h));
-
- // we're being resized and there is a freeze display request,
- // acquire a freeze lock, so that the screen stays put
- // until we've redrawn at the new size; this is to avoid
- // glitches upon orientation changes.
- if (mFlinger->hasFreezeRequest()) {
- // if the surface is hidden, don't try to acquire the
- // freeze lock, since hidden surfaces may never redraw
- if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
- mFreezeLock = mFlinger->getFreezeLock();
+ "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
+ this,
+ int(temp.requested_w), int(temp.requested_h),
+ int(front.requested_w), int(front.requested_h));
+
+ if (!isFixedSize()) {
+ // we're being resized and there is a freeze display request,
+ // acquire a freeze lock, so that the screen stays put
+ // until we've redrawn at the new size; this is to avoid
+ // glitches upon orientation changes.
+ if (mFlinger->hasFreezeRequest()) {
+ // if the surface is hidden, don't try to acquire the
+ // freeze lock, since hidden surfaces may never redraw
+ if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
+ mFreezeLock = mFlinger->getFreezeLock();
+ }
}
- }
- // this will make sure LayerBase::doTransaction doesn't update
- // the drawing state's size
- Layer::State& editDraw(mDrawingState);
- editDraw.requested_w = temp.requested_w;
- editDraw.requested_h = temp.requested_h;
+ // this will make sure LayerBase::doTransaction doesn't update
+ // the drawing state's size
+ Layer::State& editDraw(mDrawingState);
+ editDraw.requested_w = temp.requested_w;
+ editDraw.requested_h = temp.requested_h;
- // record the new size, form this point on, when the client request a
- // buffer, it'll get the new size.
- setDrawingSize(temp.requested_w, temp.requested_h);
+ // record the new size, form this point on, when the client request
+ // a buffer, it'll get the new size.
+ setBufferSize(temp.requested_w, temp.requested_h);
- // all buffers need reallocation
- lcblk->reallocate();
+ // all buffers need reallocation
+ lcblk->reallocateAll();
+ } else {
+ // record the new size
+ setBufferSize(temp.requested_w, temp.requested_h);
+ }
}
if (temp.sequence != front.sequence) {
@@ -376,12 +397,17 @@ uint32_t Layer::doTransaction(uint32_t flags)
return LayerBase::doTransaction(flags);
}
-void Layer::setDrawingSize(uint32_t w, uint32_t h) {
+void Layer::setBufferSize(uint32_t w, uint32_t h) {
Mutex::Autolock _l(mLock);
mWidth = w;
mHeight = h;
}
+bool Layer::isFixedSize() const {
+ Mutex::Autolock _l(mLock);
+ return mFixedSize;
+}
+
// ----------------------------------------------------------------------------
// pageflip handling...
// ----------------------------------------------------------------------------
@@ -677,7 +703,8 @@ Layer::SurfaceLayer::~SurfaceLayer()
{
}
-sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
+sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
{
sp<GraphicBuffer> buffer;
sp<Layer> owner(getOwner());
@@ -687,7 +714,7 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
* as it could cause a dead-lock, since it may have to wait
* on conditions updated my the main thread.
*/
- buffer = owner->requestBuffer(index, usage);
+ buffer = owner->requestBuffer(index, w, h, format, usage);
}
return buffer;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 247748b..10b5910 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -57,7 +57,8 @@ public:
status_t setBuffers(uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags=0);
- void setDrawingSize(uint32_t w, uint32_t h);
+ void setBufferSize(uint32_t w, uint32_t h);
+ bool isFixedSize() const;
virtual void onDraw(const Region& clip) const;
virtual uint32_t doTransaction(uint32_t transactionFlags);
@@ -88,7 +89,8 @@ private:
uint32_t getEffectiveUsage(uint32_t usage) const;
- sp<GraphicBuffer> requestBuffer(int index, int usage);
+ sp<GraphicBuffer> requestBuffer(int bufferIdx,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
status_t setBufferCount(int bufferCount);
class SurfaceLayer : public LayerBaseClient::Surface {
@@ -97,7 +99,8 @@ private:
SurfaceID id, const sp<Layer>& owner);
~SurfaceLayer();
private:
- virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+ virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
virtual status_t setBufferCount(int bufferCount);
sp<Layer> getOwner() const {
return static_cast<Layer*>(Surface::getOwner().get());
@@ -181,6 +184,10 @@ private:
mutable Mutex mLock;
uint32_t mWidth;
uint32_t mHeight;
+ uint32_t mReqWidth;
+ uint32_t mReqHeight;
+ uint32_t mReqFormat;
+ bool mFixedSize;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 63b9520..51673ff 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -616,7 +616,8 @@ status_t LayerBaseClient::Surface::onTransact(
return BnSurface::onTransact(code, data, reply, flags);
}
-sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int index, int usage)
+sp<GraphicBuffer> LayerBaseClient::Surface::requestBuffer(int bufferIdx,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
{
return NULL;
}
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 53b848f..569b0ff 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -301,7 +301,8 @@ public:
sp<LayerBaseClient> getOwner() const;
private:
- virtual sp<GraphicBuffer> requestBuffer(int index, int usage);
+ virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
virtual status_t setBufferCount(int bufferCount);
virtual status_t registerBuffers(const ISurface::BufferHeap& buffers);
diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/surfaceflinger_client/ISurface.cpp
index c5d0c0e..7049d9e 100644
--- a/libs/surfaceflinger_client/ISurface.cpp
+++ b/libs/surfaceflinger_client/ISurface.cpp
@@ -71,11 +71,15 @@ public:
{
}
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage)
+ virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
{
Parcel data, reply;
data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
data.writeInt32(bufferIdx);
+ data.writeInt32(w);
+ data.writeInt32(h);
+ data.writeInt32(format);
data.writeInt32(usage);
remote()->transact(REQUEST_BUFFER, data, &reply);
sp<GraphicBuffer> buffer = new GraphicBuffer();
@@ -150,8 +154,11 @@ status_t BnSurface::onTransact(
case REQUEST_BUFFER: {
CHECK_INTERFACE(ISurface, data, reply);
int bufferIdx = data.readInt32();
- int usage = data.readInt32();
- sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, usage));
+ uint32_t w = data.readInt32();
+ uint32_t h = data.readInt32();
+ uint32_t format = data.readInt32();
+ uint32_t usage = data.readInt32();
+ sp<GraphicBuffer> buffer(requestBuffer(bufferIdx, w, h, format, usage));
if (buffer == NULL)
return BAD_VALUE;
return reply->write(*buffer);
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 8681b59..b452259 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -527,13 +527,25 @@ void SharedBufferServer::setStatus(status_t status)
}
}
-status_t SharedBufferServer::reallocate()
+status_t SharedBufferServer::reallocateAll()
{
RWLock::AutoRLock _l(mLock);
SharedBufferStack& stack( *mSharedStack );
uint32_t mask = mBufferList.getMask();
- android_atomic_or(mask, &stack.reallocMask);
+ android_atomic_or(mask, &stack.reallocMask);
+ return NO_ERROR;
+}
+
+status_t SharedBufferServer::reallocateAllExcept(int buffer)
+{
+ RWLock::AutoRLock _l(mLock);
+
+ SharedBufferStack& stack( *mSharedStack );
+ BufferList temp(mBufferList);
+ temp.remove(buffer);
+ uint32_t mask = temp.getMask();
+ android_atomic_or(mask, &stack.reallocMask);
return NO_ERROR;
}
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 5f42af0..71504fa 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -349,15 +349,18 @@ void Surface::init()
const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
const_cast<uint32_t&>(android_native_window_t::flags) = 0;
// be default we request a hardware surface
- mUsage = GRALLOC_USAGE_HW_RENDER;
mConnected = 0;
+ // two buffers by default
+ mBuffers.setCapacity(2);
+ mBuffers.insertAt(0, 2);
}
Surface::~Surface()
{
// this is a client-side operation, the surface is destroyed, unmap
// its buffers in this process.
- for (int i=0 ; i<2 ; i++) {
+ size_t size = mBuffers.size();
+ for (size_t i=0 ; i<size ; i++) {
if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
}
@@ -365,6 +368,7 @@ Surface::~Surface()
// clear all references and trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
+ mBuffers.clear();
mClient.clear();
mSurface.clear();
delete mSharedBufferClient;
@@ -463,6 +467,22 @@ int Surface::perform(android_native_window_t* window,
// ----------------------------------------------------------------------------
+bool Surface::needNewBuffer(int bufIdx,
+ uint32_t *pWidth, uint32_t *pHeight,
+ uint32_t *pFormat, uint32_t *pUsage) const
+{
+ Mutex::Autolock _l(mSurfaceLock);
+
+ // Always call needNewBuffer(), since it clears the needed buffers flags
+ bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
+ bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]);
+ bool newNeewBuffer = needNewBuffer || !validBuffer;
+ if (newNeewBuffer) {
+ mBufferInfo.get(pWidth, pHeight, pFormat, pUsage);
+ }
+ return newNeewBuffer;
+}
+
int Surface::dequeueBuffer(android_native_buffer_t** buffer)
{
sp<SurfaceComposerClient> client(getClient());
@@ -476,27 +496,28 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)
return bufIdx;
}
- // below we make sure we AT LEAST have the usage flags we want
- const uint32_t usage(getUsage());
- const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
+ // grow the buffer array if needed
+ const size_t size = mBuffers.size();
+ const size_t needed = bufIdx+1;
+ if (size < needed) {
+ mBuffers.insertAt(size, needed-size);
+ }
- // Always call needNewBuffer(), since it clears the needed buffers flags
- bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx);
- if (backBuffer == 0 ||
- ((uint32_t(backBuffer->usage) & usage) != usage) ||
- needNewBuffer)
- {
- err = getBufferLocked(bufIdx, usage);
- LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
- bufIdx, usage, strerror(-err));
+ uint32_t w, h, format, usage;
+ if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) {
+ err = getBufferLocked(bufIdx, w, h, format, usage);
+ LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)",
+ bufIdx, w, h, format, usage, strerror(-err));
if (err == NO_ERROR) {
// reset the width/height with the what we get from the buffer
+ const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
mWidth = uint32_t(backBuffer->width);
mHeight = uint32_t(backBuffer->height);
}
}
// if we still don't have a buffer here, we probably ran out of memory
+ const sp<GraphicBuffer>& backBuffer(mBuffers[bufIdx]);
if (!err && backBuffer==0) {
err = NO_MEMORY;
}
@@ -614,12 +635,17 @@ int Surface::dispatch_set_buffer_count(va_list args) {
size_t bufferCount = va_arg(args, size_t);
return setBufferCount(bufferCount);
}
-
+int Surface::dispatch_set_buffers_geometry(va_list args) {
+ int w = va_arg(args, int);
+ int h = va_arg(args, int);
+ int f = va_arg(args, int);
+ return setBuffersGeometry(w, h, f);
+}
void Surface::setUsage(uint32_t reqUsage)
{
Mutex::Autolock _l(mSurfaceLock);
- mUsage = reqUsage;
+ mBufferInfo.set(reqUsage);
}
int Surface::connect(int api)
@@ -660,18 +686,6 @@ int Surface::disconnect(int api)
return err;
}
-uint32_t Surface::getUsage() const
-{
- Mutex::Autolock _l(mSurfaceLock);
- return mUsage;
-}
-
-int Surface::getConnectedApi() const
-{
- Mutex::Autolock _l(mSurfaceLock);
- return mConnected;
-}
-
int Surface::crop(Rect const* rect)
{
Mutex::Autolock _l(mSurfaceLock);
@@ -700,6 +714,26 @@ int Surface::setBufferCount(int bufferCount)
return err;
}
+int Surface::setBuffersGeometry(int w, int h, int format)
+{
+ if (w<0 || h<0 || format<0)
+ return BAD_VALUE;
+
+ if ((w && !h) || (!w && h))
+ return BAD_VALUE;
+
+ Mutex::Autolock _l(mSurfaceLock);
+ mBufferInfo.set(w, h, format);
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::getConnectedApi() const
+{
+ Mutex::Autolock _l(mSurfaceLock);
+ return mConnected;
+}
// ----------------------------------------------------------------------------
@@ -830,7 +864,8 @@ int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const
return buffer->getIndex();
}
-status_t Surface::getBufferLocked(int index, int usage)
+status_t Surface::getBufferLocked(int index,
+ uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
{
sp<ISurface> s(mSurface);
if (s == 0) return NO_INIT;
@@ -838,20 +873,21 @@ status_t Surface::getBufferLocked(int index, int usage)
status_t err = NO_MEMORY;
// free the current buffer
- sp<GraphicBuffer>& currentBuffer(mBuffers[index]);
+ sp<GraphicBuffer>& currentBuffer(mBuffers.editItemAt(index));
if (currentBuffer != 0) {
getBufferMapper().unregisterBuffer(currentBuffer->handle);
currentBuffer.clear();
}
- sp<GraphicBuffer> buffer = s->requestBuffer(index, usage);
+ sp<GraphicBuffer> buffer = s->requestBuffer(index, w, h, format, usage);
LOGE_IF(buffer==0,
"ISurface::getBuffer(%d, %08x) returned NULL",
index, usage);
if (buffer != 0) { // this should never happen by construction
LOGE_IF(buffer->handle == NULL,
- "Surface (identity=%d) requestBuffer(%d, %08x) returned"
- "a buffer with a null handle", mIdentity, index, usage);
+ "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) "
+ "returned a buffer with a null handle",
+ mIdentity, index, w, h, format, usage);
err = mSharedBufferClient->getStatus();
LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err);
if (!err && buffer->handle != NULL) {
@@ -869,5 +905,44 @@ status_t Surface::getBufferLocked(int index, int usage)
return err;
}
+// ----------------------------------------------------------------------------
+Surface::BufferInfo::BufferInfo()
+ : mWidth(0), mHeight(0), mFormat(0),
+ mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0)
+{
+}
+
+void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) {
+ if ((mWidth != w) || (mHeight != h) || (mFormat != format)) {
+ mWidth = w;
+ mHeight = h;
+ mFormat = format;
+ mDirty |= GEOMETRY;
+ }
+}
+
+void Surface::BufferInfo::set(uint32_t usage) {
+ mUsage = usage;
+}
+
+void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight,
+ uint32_t *pFormat, uint32_t *pUsage) const {
+ *pWidth = mWidth;
+ *pHeight = mHeight;
+ *pFormat = mFormat;
+ *pUsage = mUsage;
+}
+
+bool Surface::BufferInfo::validateBuffer(const sp<GraphicBuffer>& buffer) const {
+ // make sure we AT LEAST have the usage flags we want
+ if (mDirty || buffer==0 ||
+ ((buffer->usage & mUsage) != mUsage)) {
+ mDirty = 0;
+ return false;
+ }
+ return true;
+}
+
+// ----------------------------------------------------------------------------
}; // namespace android