Skip to content

Commit 2195604

Browse files
committed
fix [3361121] hang in glClear() - device unresponsive, OTA fails (DO NOT MERGE)
Generally we never want to lock a buffer for write access if it is at the "head" on the surfaceflinger side. The only exception (1) is when the buffer is not currently in use AND there is at least one queued buffer -- in which case, SurfaceFlinger will never use said buffer anymore, because on the next composition around, it will be able to retire the first queued buffer. The logic above relies on SurfaceFlinger always retiring and locking a buffer before composition -- unfortunately this didn't happen during a screenshot. This could leave us in a situation where a buffer is locked by the application for write, and used by SurfaceFlinger for texturing, causing a hang. Here, we fix this issue by never assuming the exception (1), it was intended as an optimization allowing ANativeWindow::lockBuffer() to return sooner and was justified when most of SF composition was done in software. The actual buffer locking is now ensured by gralloc. We could have handled screenshots in a similar way to a regular composition, but it could have caused glitches on screen, essentially, taking a screenshot could cause to skip a frame. now that we removed the notion of a "inUse" buffer in surfaceflinger a lot of code can be simplified / removed. noteworthy, the whole concept of "unlockClient" wrt. "compositionComplete" is also gone.
1 parent 68d3478 commit 2195604

File tree

8 files changed

+4
-82
lines changed

8 files changed

+4
-82
lines changed

include/private/surfaceflinger/SharedBufferStack.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ class SharedBufferStack
105105
volatile int32_t head; // server's current front buffer
106106
volatile int32_t available; // number of dequeue-able buffers
107107
volatile int32_t queued; // number of buffers waiting for post
108-
volatile int32_t inUse; // buffer currently in use by SF
108+
volatile int32_t reserved1;
109109
volatile status_t status; // surface's status code
110110

111111
// not part of the conditions
@@ -275,7 +275,6 @@ class SharedBufferServer
275275
int32_t identity);
276276

277277
ssize_t retireAndLock();
278-
status_t unlock(int buffer);
279278
void setStatus(status_t status);
280279
status_t reallocateAll();
281280
status_t reallocateAllExcept(int buffer);
@@ -346,11 +345,6 @@ class SharedBufferServer
346345
int mNumBuffers;
347346
BufferList mBufferList;
348347

349-
struct UnlockUpdate : public UpdateBase {
350-
const int lockedBuffer;
351-
inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer);
352-
inline ssize_t operator()();
353-
};
354348

355349
struct RetireUpdate : public UpdateBase {
356350
const int numBuffers;

libs/surfaceflinger_client/SharedBufferStack.cpp

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ SharedBufferStack::SharedBufferStack()
5858

5959
void SharedBufferStack::init(int32_t i)
6060
{
61-
inUse = -2;
6261
status = NO_ERROR;
6362
identity = i;
6463
}
@@ -199,9 +198,9 @@ String8 SharedBufferBase::dump(char const* prefix) const
199198
SharedBufferStack& stack( *mSharedStack );
200199
snprintf(buffer, SIZE,
201200
"%s[ head=%2d, available=%2d, queued=%2d ] "
202-
"reallocMask=%08x, inUse=%2d, identity=%d, status=%d",
201+
"reallocMask=%08x, identity=%d, status=%d",
203202
prefix, stack.head, stack.available, stack.queued,
204-
stack.reallocMask, stack.inUse, stack.identity, stack.status);
203+
stack.reallocMask, stack.identity, stack.status);
205204
result.append(buffer);
206205
result.append("\n");
207206
return result;
@@ -261,8 +260,7 @@ bool SharedBufferClient::LockCondition::operator()() const {
261260
// NOTE: if stack.head is messed up, we could crash the client
262261
// or cause some drawing artifacts. This is okay, as long as it is
263262
// limited to the client.
264-
return (buf != stack.index[stack.head] ||
265-
(stack.queued > 0 && stack.inUse != buf));
263+
return (buf != stack.index[stack.head]);
266264
}
267265

268266
// ----------------------------------------------------------------------------
@@ -295,22 +293,6 @@ ssize_t SharedBufferClient::CancelUpdate::operator()() {
295293
return NO_ERROR;
296294
}
297295

298-
SharedBufferServer::UnlockUpdate::UnlockUpdate(
299-
SharedBufferBase* sbb, int lockedBuffer)
300-
: UpdateBase(sbb), lockedBuffer(lockedBuffer) {
301-
}
302-
ssize_t SharedBufferServer::UnlockUpdate::operator()() {
303-
if (stack.inUse != lockedBuffer) {
304-
LOGE("unlocking %d, but currently locked buffer is %d "
305-
"(identity=%d, token=%d)",
306-
lockedBuffer, stack.inUse,
307-
stack.identity, stack.token);
308-
return BAD_VALUE;
309-
}
310-
android_atomic_write(-1, &stack.inUse);
311-
return NO_ERROR;
312-
}
313-
314296
SharedBufferServer::RetireUpdate::RetireUpdate(
315297
SharedBufferBase* sbb, int numBuffers)
316298
: UpdateBase(sbb), numBuffers(numBuffers) {
@@ -320,9 +302,6 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() {
320302
if (uint32_t(head) >= SharedBufferStack::NUM_BUFFER_MAX)
321303
return BAD_VALUE;
322304

323-
// Preventively lock the current buffer before updating queued.
324-
android_atomic_write(stack.headBuf, &stack.inUse);
325-
326305
// Decrement the number of queued buffers
327306
int32_t queued;
328307
do {
@@ -338,7 +317,6 @@ ssize_t SharedBufferServer::RetireUpdate::operator()() {
338317
head = (head + 1) % numBuffers;
339318
const int8_t headBuf = stack.index[head];
340319
stack.headBuf = headBuf;
341-
android_atomic_write(headBuf, &stack.inUse);
342320

343321
// head is only modified here, so we don't need to use cmpxchg
344322
android_atomic_write(head, &stack.head);
@@ -542,13 +520,6 @@ ssize_t SharedBufferServer::retireAndLock()
542520
return buf;
543521
}
544522

545-
status_t SharedBufferServer::unlock(int buf)
546-
{
547-
UnlockUpdate update(this, buf);
548-
status_t err = updateCondition( update );
549-
return err;
550-
}
551-
552523
void SharedBufferServer::setStatus(status_t status)
553524
{
554525
if (status < NO_ERROR) {

services/surfaceflinger/Layer.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -682,22 +682,6 @@ void Layer::unlockPageFlip(
682682
}
683683
}
684684

685-
void Layer::finishPageFlip()
686-
{
687-
ClientRef::Access sharedClient(mUserClientRef);
688-
SharedBufferServer* lcblk(sharedClient.get());
689-
if (lcblk) {
690-
int buf = mBufferManager.getActiveBufferIndex();
691-
if (buf >= 0) {
692-
status_t err = lcblk->unlock( buf );
693-
LOGE_IF(err!=NO_ERROR,
694-
"layer %p, buffer=%d wasn't locked!",
695-
this, buf);
696-
}
697-
}
698-
}
699-
700-
701685
void Layer::dump(String8& result, char* buffer, size_t SIZE) const
702686
{
703687
LayerBaseClient::dump(result, buffer, SIZE);

services/surfaceflinger/Layer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ class Layer : public LayerBaseClient
7373
virtual uint32_t doTransaction(uint32_t transactionFlags);
7474
virtual void lockPageFlip(bool& recomputeVisibleRegions);
7575
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
76-
virtual void finishPageFlip();
7776
virtual bool needsBlending() const { return mNeedsBlending; }
7877
virtual bool needsDithering() const { return mNeedsDithering; }
7978
virtual bool needsFiltering() const;

services/surfaceflinger/LayerBase.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,6 @@ void LayerBase::unlockPageFlip(
273273
}
274274
}
275275

276-
void LayerBase::finishPageFlip()
277-
{
278-
}
279-
280276
void LayerBase::invalidate()
281277
{
282278
if ((android_atomic_or(1, &mInvalidate)&1) == 0) {

services/surfaceflinger/LayerBase.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,6 @@ class LayerBase : public RefBase
173173
*/
174174
virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
175175

176-
/**
177-
* finishPageFlip - called after all surfaces have drawn.
178-
*/
179-
virtual void finishPageFlip();
180-
181176
/**
182177
* needsBlending - true if this surface needs blending
183178
*/

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -396,18 +396,13 @@ bool SurfaceFlinger::threadLoop()
396396
logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
397397
hw.compositionComplete();
398398

399-
// release the clients before we flip ('cause flip might block)
400-
logger.log(GraphicLog::SF_UNLOCK_CLIENTS, index);
401-
unlockClients();
402-
403399
logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
404400
postFramebuffer();
405401

406402
logger.log(GraphicLog::SF_REPAINT_DONE, index);
407403
} else {
408404
// pretend we did the post
409405
hw.compositionComplete();
410-
unlockClients();
411406
usleep(16667); // 60 fps period
412407
}
413408
return true;
@@ -895,17 +890,6 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
895890
}
896891
}
897892

898-
void SurfaceFlinger::unlockClients()
899-
{
900-
const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
901-
const size_t count = drawingLayers.size();
902-
sp<LayerBase> const* const layers = drawingLayers.array();
903-
for (size_t i=0 ; i<count ; ++i) {
904-
const sp<LayerBase>& layer = layers[i];
905-
layer->finishPageFlip();
906-
}
907-
}
908-
909893
void SurfaceFlinger::debugFlashRegions()
910894
{
911895
const DisplayHardware& hw(graphicPlane(0).displayHardware());

services/surfaceflinger/SurfaceFlinger.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ class SurfaceFlinger :
310310
bool handleBypassLayer();
311311
void postFramebuffer();
312312
void composeSurfaces(const Region& dirty);
313-
void unlockClients();
314313

315314

316315
ssize_t addClientLayer(const sp<Client>& client,

0 commit comments

Comments
 (0)