merge in jb-mr2-release history after reset to jb-mr2-dev
diff --git a/include/ui/Fence.h b/include/ui/Fence.h
index 81d5d09..60156e7 100644
--- a/include/ui/Fence.h
+++ b/include/ui/Fence.h
@@ -70,9 +70,10 @@
// waitForever is a convenience function for waiting forever for a fence to
// signal (just like wait(TIMEOUT_NEVER)), but issuing an error to the
// system log and fence state to the kernel log if the wait lasts longer
- // than warningTimeout. The logname argument should be a string identifying
+ // than a warning timeout.
+ // The logname argument should be a string identifying
// the caller and will be included in the log message.
- status_t waitForever(unsigned int warningTimeout, const char* logname);
+ status_t waitForever(const char* logname);
// merge combines two Fence objects, creating a new Fence object that
// becomes signaled when both f1 and f2 are signaled (even if f1 or f2 is
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 90619ab..7db1b84 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -63,7 +63,7 @@
}
if (waitForFence) {
- err = item->mFence->waitForever(1000, "BufferItemConsumer::acquireBuffer");
+ err = item->mFence->waitForever("BufferItemConsumer::acquireBuffer");
if (err != OK) {
BI_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
strerror(-err), err);
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 91af78d..0543649 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -80,7 +80,7 @@
int buf = b.mBuf;
if (b.mFence.get()) {
- err = b.mFence->waitForever(1000, "CpuConsumer::lockNextBuffer");
+ err = b.mFence->waitForever("CpuConsumer::lockNextBuffer");
if (err != OK) {
CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
strerror(-err), err);
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 637a403..bec0f90 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -821,7 +821,7 @@
return UNKNOWN_ERROR;
}
} else {
- status_t err = mCurrentFence->waitForever(1000,
+ status_t err = mCurrentFence->waitForever(
"GLConsumer::doGLFenceWaitLocked");
if (err != NO_ERROR) {
ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 4a58023..a616c1e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -113,7 +113,7 @@
int fenceFd = -1;
int result = c->dequeueBuffer(&buf, &fenceFd);
sp<Fence> fence(new Fence(fenceFd));
- int waitResult = fence->waitForever(1000, "dequeueBuffer_DEPRECATED");
+ int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
if (waitResult != OK) {
ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an error: %d",
waitResult);
@@ -734,7 +734,7 @@
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
sp<Fence> fence(new Fence(fenceFd));
- err = fence->waitForever(1000, "Surface::lock");
+ err = fence->waitForever("Surface::lock");
if (err != OK) {
ALOGE("Fence::wait failed (%s)", strerror(-err));
cancelBuffer(out, fenceFd);
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index b9e0f00..464ee86 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -54,11 +54,12 @@
return err < 0 ? -errno : status_t(NO_ERROR);
}
-status_t Fence::waitForever(unsigned int warningTimeout, const char* logname) {
+status_t Fence::waitForever(const char* logname) {
ATRACE_CALL();
if (mFenceFd == -1) {
return NO_ERROR;
}
+ unsigned int warningTimeout = 3000;
int err = sync_wait(mFenceFd, warningTimeout);
if (err < 0 && errno == ETIME) {
ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index f0f7463..a9afbe5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -750,7 +750,7 @@
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
return setFramebufferTarget(id, acquireFence, buffer);
} else {
- acquireFence->waitForever(1000, "HWComposer::fbPost");
+ acquireFence->waitForever("HWComposer::fbPost");
return mFbDev->post(mFbDev, buffer->handle);
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e647275..1cc5eb2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2567,6 +2567,86 @@
// Capture screen into an IGraphiBufferProducer
// ---------------------------------------------------------------------------
+/* The code below is here to handle b/8734824
+ *
+ * We create a IGraphicBufferProducer wrapper that forwards all calls
+ * to the calling binder thread, where they are executed. This allows
+ * the calling thread to be reused (on the other side) and not
+ * depend on having "enough" binder threads to handle the requests.
+ *
+ */
+
+class GraphicProducerWrapper : public BBinder, public MessageHandler {
+ sp<IGraphicBufferProducer> impl;
+ sp<Looper> looper;
+ status_t result;
+ bool exitPending;
+ bool exitRequested;
+ mutable Barrier barrier;
+ volatile int32_t memoryBarrier;
+ uint32_t code;
+ Parcel const* data;
+ Parcel* reply;
+
+ enum {
+ MSG_API_CALL,
+ MSG_EXIT
+ };
+
+ /*
+ * this is called by our "fake" BpGraphicBufferProducer. We package the
+ * data and reply Parcel and forward them to the calling thread.
+ */
+ virtual status_t transact(uint32_t code,
+ const Parcel& data, Parcel* reply, uint32_t flags) {
+ this->code = code;
+ this->data = &data;
+ this->reply = reply;
+ android_atomic_acquire_store(0, &memoryBarrier);
+ if (exitPending) {
+ // if we've exited, we run the message synchronously right here
+ handleMessage(Message(MSG_API_CALL));
+ } else {
+ barrier.close();
+ looper->sendMessage(this, Message(MSG_API_CALL));
+ barrier.wait();
+ }
+ return NO_ERROR;
+ }
+
+ /*
+ * here we run on the binder calling thread. All we've got to do is
+ * call the real BpGraphicBufferProducer.
+ */
+ virtual void handleMessage(const Message& message) {
+ android_atomic_release_load(&memoryBarrier);
+ if (message.what == MSG_API_CALL) {
+ impl->asBinder()->transact(code, data[0], reply);
+ barrier.open();
+ } else if (message.what == MSG_EXIT) {
+ exitRequested = true;
+ }
+ }
+
+public:
+ GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl) :
+ impl(impl), looper(new Looper(true)), result(NO_ERROR),
+ exitPending(false), exitRequested(false) {
+ }
+
+ status_t waitForResponse() {
+ do {
+ looper->pollOnce(-1);
+ } while (!exitRequested);
+ return result;
+ }
+
+ void exit(status_t result) {
+ exitPending = true;
+ looper->sendMessage(this, Message(MSG_EXIT));
+ }
+};
+
status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
@@ -2579,24 +2659,25 @@
if (CC_UNLIKELY(producer == 0))
return BAD_VALUE;
+
class MessageCaptureScreen : public MessageBase {
SurfaceFlinger* flinger;
sp<IBinder> display;
sp<IGraphicBufferProducer> producer;
uint32_t reqWidth, reqHeight;
uint32_t minLayerZ,maxLayerZ;
- bool isCpuConsumer;
+ bool useReadPixels;
status_t result;
public:
MessageCaptureScreen(SurfaceFlinger* flinger,
const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
- uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer)
+ uint32_t minLayerZ, uint32_t maxLayerZ, bool useReadPixels)
: flinger(flinger), display(display), producer(producer),
reqWidth(reqWidth), reqHeight(reqHeight),
minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
- isCpuConsumer(isCpuConsumer),
+ useReadPixels(useReadPixels),
result(PERMISSION_DENIED)
{
}
@@ -2606,26 +2687,6 @@
virtual bool handler() {
Mutex::Autolock _l(flinger->mStateLock);
sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
-
- bool useReadPixels = false;
- if (isCpuConsumer) {
- bool formatSupportedBytBitmap =
- (flinger->mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBA_8888) ||
- (flinger->mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBX_8888);
- if (formatSupportedBytBitmap == false) {
- // the pixel format we have is not compatible with
- // Bitmap.java, which is the likely client of this API,
- // so we just revert to glReadPixels() in that case.
- useReadPixels = true;
- }
- if (flinger->mGpuToCpuSupported == false) {
- // When we know the GL->CPU path works, we can call
- // captureScreenImplLocked() directly, instead of using the
- // glReadPixels() workaround.
- useReadPixels = true;
- }
- }
-
if (!useReadPixels) {
result = flinger->captureScreenImplLocked(hw,
producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
@@ -2633,6 +2694,7 @@
result = flinger->captureScreenImplCpuConsumerLocked(hw,
producer, reqWidth, reqHeight, minLayerZ, maxLayerZ);
}
+ static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result);
return true;
}
};
@@ -2644,12 +2706,40 @@
// scheduled at this time, this will end-up being a no-op as well.
mEventQueue.invalidateTransactionNow();
+ bool useReadPixels = false;
+ if (isCpuConsumer) {
+ bool formatSupportedBytBitmap =
+ (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBA_8888) ||
+ (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBX_8888);
+ if (formatSupportedBytBitmap == false) {
+ // the pixel format we have is not compatible with
+ // Bitmap.java, which is the likely client of this API,
+ // so we just revert to glReadPixels() in that case.
+ useReadPixels = true;
+ }
+ if (mGpuToCpuSupported == false) {
+ // When we know the GL->CPU path works, we can call
+ // captureScreenImplLocked() directly, instead of using the
+ // glReadPixels() workaround.
+ useReadPixels = true;
+ }
+ }
+
+ // this creates a "fake" BBinder which will serve as a "fake" remote
+ // binder to receive the marshaled calls and forward them to the
+ // real remote (a BpGraphicBufferProducer)
+ sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
+
+ // the asInterface() call below creates our "fake" BpGraphicBufferProducer
+ // which does the marshaling work forwards to our "fake remote" above.
sp<MessageBase> msg = new MessageCaptureScreen(this,
- display, producer, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- isCpuConsumer);
- status_t res = postMessageSync(msg);
+ display, IGraphicBufferProducer::asInterface( wrapper ),
+ reqWidth, reqHeight, minLayerZ, maxLayerZ,
+ useReadPixels);
+
+ status_t res = postMessageAsync(msg);
if (res == NO_ERROR) {
- res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
+ res = wrapper->waitForResponse();
}
return res;
}