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
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 @@
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 @@
{
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 @@
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 @@
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 @@
*/
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;
+ }
- Mutex::Autolock _l(mLock);
- uint32_t w = mWidth;
- uint32_t h = mHeight;
-
- sp<Buffer>& buffer(mBuffers[index]);
+ uint32_t w, h;
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+ w = mWidth;
+ h = mHeight;
+ buffer = mBuffers[index];
+ mBuffers[index].clear();
+ }
+
+
if (buffer->getStrongCount() == 1) {
err = buffer->reallocate(w, h, mFormat, usage, mBufferFlags);
} else {
@@ -253,8 +279,16 @@
}
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;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 3b4489e..2e8173d 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -51,10 +51,6 @@
static const char* const typeID;
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
-
-
- SharedBufferServer* lcblk;
-
Layer(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
@@ -88,6 +84,8 @@
return mBuffers[mFrontBufferIndex];
}
+ virtual void onRemoved();
+
void reloadTexture(const Region& dirty);
sp<SurfaceBuffer> requestBuffer(int index, int usage);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 62e41b0..1f22488 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -642,9 +642,12 @@
LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
- : LayerBase(flinger, display), client(client),
+ : LayerBase(flinger, display), lcblk(NULL), client(client),
mIndex(i), mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
{
+ lcblk = new SharedBufferServer(
+ client->ctrlblk, i, NUM_BUFFERS,
+ mIdentity);
}
void LayerBaseClient::onFirstRef()
@@ -652,8 +655,6 @@
sp<Client> client(this->client.promote());
if (client != 0) {
client->bindLayer(this, mIndex);
- // Initialize this layer's identity
- client->ctrlblk->setIdentity(mIndex, mIdentity);
}
}
@@ -663,6 +664,7 @@
if (client != 0) {
client->free(mIndex);
}
+ delete lcblk;
}
int32_t LayerBaseClient::serverIndex() const
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 78bb4bf..3a52240 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -292,13 +292,16 @@
virtual char const* getTypeID() const { return typeID; }
virtual uint32_t getTypeInfo() const { return typeInfo; }
+ // lcblk is (almost) only accessed from the main SF thread, in the places
+ // where it's not, a reference to Client must be held
+ SharedBufferServer* lcblk;
+
LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i);
virtual ~LayerBaseClient();
virtual void onFirstRef();
- wp<Client> client;
-// SharedBufferServer* lcblk;
+ const wp<Client> client;
inline uint32_t getIdentity() const { return mIdentity; }
inline int32_t clientIndex() const { return mIndex; }
@@ -308,6 +311,7 @@
sp<Surface> getSurface();
virtual sp<Surface> createSurface() const;
+ virtual void onRemoved() { }
class Surface : public BnSurface
{
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index b368db6..8685f99 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -654,6 +654,7 @@
// some layers might have been removed, so
// we need to update the regions they're exposing.
if (mLayersRemoved) {
+ mLayersRemoved = false;
mVisibleRegionsDirty = true;
const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
const size_t count = previousLayers.size();
@@ -1093,9 +1094,6 @@
void SurfaceFlinger::free_resources_l()
{
- // Destroy layers that were removed
- mLayersRemoved = false;
-
// free resources associated with disconnected clients
Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
const size_t count = disconnectedClients.size();
@@ -1321,11 +1319,15 @@
* to wait for all client's references to go away first).
*/
+ status_t err = NAME_NOT_FOUND;
Mutex::Autolock _l(mStateLock);
sp<LayerBaseClient> layer = getLayerUser_l(index);
- status_t err = purgatorizeLayer_l(layer);
- if (err == NO_ERROR) {
- setTransactionFlags(eTransactionNeeded);
+ if (layer != 0) {
+ err = purgatorizeLayer_l(layer);
+ if (err == NO_ERROR) {
+ layer->onRemoved();
+ setTransactionFlags(eTransactionNeeded);
+ }
}
return err;
}
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 73fb582..3fbd8c7 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -53,21 +53,20 @@
return uint32_t(surfaces[token].identity);
}
-status_t SharedClient::setIdentity(size_t token, uint32_t identity) {
- if (token >= NUM_LAYERS_MAX)
- return BAD_INDEX;
- surfaces[token].identity = identity;
- return NO_ERROR;
-}
-
// ----------------------------------------------------------------------------
SharedBufferStack::SharedBufferStack()
- : inUse(-1), status(NO_ERROR), identity(-1)
{
}
+void SharedBufferStack::init(int32_t i)
+{
+ inUse = -1;
+ status = NO_ERROR;
+ identity = i;
+}
+
status_t SharedBufferStack::setDirtyRegion(int buffer, const Region& dirty)
{
if (uint32_t(buffer) >= NUM_BUFFER_MAX)
@@ -312,9 +311,10 @@
// ----------------------------------------------------------------------------
SharedBufferServer::SharedBufferServer(SharedClient* sharedClient,
- int surface, int num)
+ int surface, int num, int32_t identity)
: SharedBufferBase(sharedClient, surface, num)
{
+ mSharedStack->init(identity);
mSharedStack->head = num-1;
mSharedStack->available = num;
mSharedStack->queued = 0;