gui: Surface::dequeueBuffer no locker holds mutex while blocking in binder
- This also fixes a hang in the camera service when trying to shut down
if the producer is infinitely blocked while trying to get a new buffer.
Bug: 13250382
Change-Id: I32ca82162bb8645b97dbe084e13e05ca05529a42
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 975d005..b628a15 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -178,19 +178,38 @@
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
ALOGV("Surface::dequeueBuffer");
- Mutex::Autolock lock(mMutex);
+
+ int reqW;
+ int reqH;
+ bool swapIntervalZero;
+ uint32_t reqFormat;
+ uint32_t reqUsage;
+
+ {
+ Mutex::Autolock lock(mMutex);
+
+ reqW = mReqWidth ? mReqWidth : mUserWidth;
+ reqH = mReqHeight ? mReqHeight : mUserHeight;
+
+ swapIntervalZero = mSwapIntervalZero;
+ reqFormat = mReqFormat;
+ reqUsage = mReqUsage;
+ } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
+
int buf = -1;
- int reqW = mReqWidth ? mReqWidth : mUserWidth;
- int reqH = mReqHeight ? mReqHeight : mUserHeight;
sp<Fence> fence;
- status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, mSwapIntervalZero,
- reqW, reqH, mReqFormat, mReqUsage);
+ status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
+ reqW, reqH, reqFormat, reqUsage);
+
if (result < 0) {
- ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d)"
- "failed: %d", mReqWidth, mReqHeight, mReqFormat, mReqUsage,
+ ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
+ "failed: %d", swapIntervalZero, reqW, reqH, reqFormat, reqUsage,
result);
return result;
}
+
+ Mutex::Autolock lock(mMutex);
+
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen