diff options
author | Mathias Agopian <mathias@google.com> | 2009-09-10 19:41:18 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-09-10 19:41:18 -0700 |
commit | 48d819a1315f7d1b5abfec9d4fd34fb5aed27b1d (patch) | |
tree | 610ef98303e468061f68511380991e4b65bd547a /libs/surfaceflinger/Layer.cpp | |
parent | b58b5d72d6877300fe39b2a30b4742c6f962833f (diff) | |
download | frameworks_native-48d819a1315f7d1b5abfec9d4fd34fb5aed27b1d.zip frameworks_native-48d819a1315f7d1b5abfec9d4fd34fb5aed27b1d.tar.gz frameworks_native-48d819a1315f7d1b5abfec9d4fd34fb5aed27b1d.tar.bz2 |
fix [2112575] stuck on DequeueCondition for a surface that doesn't exist anymore
this also fixes part of [2111536] Device is soft rebooted after ending the call through voice dialer
Diffstat (limited to 'libs/surfaceflinger/Layer.cpp')
-rw-r--r-- | libs/surfaceflinger/Layer.cpp | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index ecb6b32..6275910 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -49,13 +49,12 @@ const char* const Layer::typeID = "Layer"; Layer::Layer(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& c, int32_t i) - : LayerBaseClient(flinger, display, c, i), lcblk(NULL), + : LayerBaseClient(flinger, display, c, i), mSecure(false), mNeedsBlending(true) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. - lcblk = new SharedBufferServer(c->ctrlblk, i, NUM_BUFFERS); mFrontBufferIndex = lcblk->getFrontBuffer(); } @@ -63,8 +62,14 @@ Layer::~Layer() { destroy(); // the actual buffers will be destroyed here - delete lcblk; +} +// called with SurfaceFlinger::mStateLock as soon as the layer is entered +// in the purgatory list +void Layer::onRemoved() +{ + // wake up the condition + lcblk->setStatus(NO_INIT); } void Layer::destroy() @@ -79,7 +84,9 @@ void Layer::destroy() eglDestroyImageKHR(dpy, mTextures[i].image); mTextures[i].image = EGL_NO_IMAGE_KHR; } + Mutex::Autolock _l(mLock); mBuffers[i].clear(); + mWidth = mHeight = 0; } mSurface.clear(); } @@ -213,6 +220,16 @@ void Layer::onDraw(const Region& clip) const sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage) { + sp<Buffer> buffer; + + // this ensures our client doesn't go away while we're accessing + // the shared area. + sp<Client> ourClient(client.promote()); + if (ourClient == 0) { + // oops, the client is already gone + return buffer; + } + /* * This is called from the client's Surface::dequeue(). This can happen * at any time, especially while we're in the middle of using the @@ -225,12 +242,21 @@ sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage) */ status_t err = lcblk->assertReallocate(index); LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err)); + if (err != NO_ERROR) { + // the surface may have died + return buffer; + } + + uint32_t w, h; + { // scope for the lock + Mutex::Autolock _l(mLock); + w = mWidth; + h = mHeight; + buffer = mBuffers[index]; + mBuffers[index].clear(); + } + - Mutex::Autolock _l(mLock); - uint32_t w = mWidth; - uint32_t h = mHeight; - - sp<Buffer>& buffer(mBuffers[index]); if (buffer->getStrongCount() == 1) { err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags); } else { @@ -253,8 +279,16 @@ sp<SurfaceBuffer> Layer::requestBuffer(int index, int usage) } if (err == NO_ERROR && buffer->handle != 0) { - // texture is now dirty... - mTextures[index].dirty = true; + Mutex::Autolock _l(mLock); + if (mWidth && mHeight) { + // and we have new buffer + mBuffers[index] = buffer; + // texture is now dirty... + mTextures[index].dirty = true; + } else { + // oops we got killed while we were allocating the buffer + buffer.clear(); + } } return buffer; } |