Return fence from acquireBuffer

Change-Id: Iab22054c1dc4fd84affab3cc5bbdcd5a1e689666
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 7c1fcb9..0d36baa 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -202,6 +202,9 @@
 
         // mBuf is the slot index of this buffer
         int mBuf;
+
+        // mFence is a fence that will signal when the buffer is idle.
+        sp<Fence> mFence;
     };
 
     // The following public functions is the consumer facing interface
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index a868537..23e3a4f 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -885,11 +885,13 @@
         buffer->mFrameNumber = mSlots[buf].mFrameNumber;
         buffer->mTimestamp = mSlots[buf].mTimestamp;
         buffer->mBuf = buf;
+        buffer->mFence = mSlots[buf].mFence;
         mSlots[buf].mAcquireCalled = true;
 
         mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
         mQueue.erase(front);
         mDequeueCondition.broadcast();
+        mSlots[buf].mFence.clear();
 
         ATRACE_INT(mConsumerName.string(), mQueue.size());
     } else {
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index bf2539f..513828c 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -114,6 +114,15 @@
         mBufferSlot[buf] = b.mGraphicBuffer;
     }
 
+    if (b.mFence.get()) {
+        err = b.mFence->wait(Fence::TIMEOUT_NEVER);
+        if (err != OK) {
+            CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
+                    strerror(-err), err);
+            return err;
+        }
+    }
+
     err = mBufferSlot[buf]->lock(
         GraphicBuffer::USAGE_SW_READ_OFTEN,
         b.mCrop,
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 9a36bf9..435a665 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -236,8 +236,7 @@
         // not accept this buffer. this is used by SurfaceFlinger to
         // reject buffers which have the wrong size
         if (rejecter && rejecter->reject(mEGLSlots[buf].mGraphicBuffer, item)) {
-            mBufferQueue->releaseBuffer(buf, dpy, EGL_NO_SYNC_KHR,
-                    Fence::NO_FENCE);
+            mBufferQueue->releaseBuffer(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);
             glBindTexture(mTexTarget, mTexName);
             return NO_ERROR;
         }
@@ -261,6 +260,14 @@
             }
         }
 
+        // Temporary; fence will be provided to clients soon
+        if (item.mFence.get()) {
+            err = item.mFence->wait(Fence::TIMEOUT_NEVER);
+            if (err != OK) {
+                ST_LOGE("updateTexImage: failure waiting for fence: %d", err);
+            }
+        }
+
         if (err == NO_ERROR) {
             GLint error;
             while ((error = glGetError()) != GL_NO_ERROR) {
@@ -284,8 +291,7 @@
         if (err != NO_ERROR) {
             // Release the buffer we just acquired.  It's not safe to
             // release the old buffer, so instead we just drop the new frame.
-            mBufferQueue->releaseBuffer(buf, dpy, EGL_NO_SYNC_KHR,
-                    Fence::NO_FENCE);
+            mBufferQueue->releaseBuffer(buf, dpy, EGL_NO_SYNC_KHR, item.mFence);
             return err;
         }
 
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 02d2b10..6cfb190 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -106,6 +106,16 @@
                     if (item.mGraphicBuffer != 0) {
                         self->mBuffers[item.mBuf] = item.mGraphicBuffer;
                     }
+                    if (item.mFence.get()) {
+                        err = item.mFence->wait(Fence::TIMEOUT_NEVER);
+                        if (err) {
+                            ALOGE("failed waiting for buffer's fence: %d", err);
+                            self->mBufferQueue->releaseBuffer(item.mBuf,
+                                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
+                                    item.mFence);
+                            return;
+                        }
+                    }
                     self->fbDev->post(self->fbDev, self->mBuffers[item.mBuf]->handle);
                     if (self->mCurrentBufferIndex >= 0) {
                         self->mBufferQueue->releaseBuffer(self->mCurrentBufferIndex,