summaryrefslogtreecommitdiffstats
path: root/libs/surfaceflinger/Layer.cpp
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2009-09-10 19:41:18 -0700
committerMathias Agopian <mathias@google.com>2009-09-10 19:41:18 -0700
commit48d819a1315f7d1b5abfec9d4fd34fb5aed27b1d (patch)
tree610ef98303e468061f68511380991e4b65bd547a /libs/surfaceflinger/Layer.cpp
parentb58b5d72d6877300fe39b2a30b4742c6f962833f (diff)
downloadframeworks_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.cpp54
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;
}