am bd20e551: Merge "Use asynchronous lock/unlock API"

* commit 'bd20e551f64234142e1146f9fa4b2dcebbd72122':
  Use asynchronous lock/unlock API
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 3cf628c..b973c40 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -97,6 +97,11 @@
     status_t lockYCbCr(uint32_t usage, android_ycbcr *ycbcr);
     status_t lockYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr);
     status_t unlock();
+    status_t lockAsync(uint32_t usage, void** vaddr, int fenceFd);
+    status_t lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd);
+    status_t lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd);
+    status_t lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd);
+    status_t unlockAsync(int *fenceFd);
 
     ANativeWindowBuffer* getNativeBuffer() const;
 
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index 99d8723..98fff0e 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -49,6 +49,14 @@
             int usage, const Rect& bounds, android_ycbcr *ycbcr);
 
     status_t unlock(buffer_handle_t handle);
+
+    status_t lockAsync(buffer_handle_t handle,
+            int usage, const Rect& bounds, void** vaddr, int fenceFd);
+
+    status_t lockAsyncYCbCr(buffer_handle_t handle,
+            int usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd);
+
+    status_t unlockAsync(buffer_handle_t handle, int *fenceFd);
     
     // dumps information about the mapping of this handle
     void dump(buffer_handle_t handle);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 27dbc4e..21ffc06 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -740,15 +740,6 @@
     ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
     if (err == NO_ERROR) {
         sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
-        sp<Fence> fence(new Fence(fenceFd));
-
-        err = fence->waitForever("Surface::lock");
-        if (err != OK) {
-            ALOGE("Fence::wait failed (%s)", strerror(-err));
-            cancelBuffer(out, fenceFd);
-            return err;
-        }
-
         const Rect bounds(backBuffer->width, backBuffer->height);
 
         Region newDirtyRegion;
@@ -799,9 +790,9 @@
         }
 
         void* vaddr;
-        status_t res = backBuffer->lock(
+        status_t res = backBuffer->lockAsync(
                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
-                newDirtyRegion.bounds(), &vaddr);
+                newDirtyRegion.bounds(), &vaddr, fenceFd);
 
         ALOGW_IF(res, "failed locking buffer (handle = %p)",
                 backBuffer->handle);
@@ -827,10 +818,11 @@
         return INVALID_OPERATION;
     }
 
-    status_t err = mLockedBuffer->unlock();
+    int fd = -1;
+    status_t err = mLockedBuffer->unlockAsync(&fd);
     ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
 
-    err = queueBuffer(mLockedBuffer.get(), -1);
+    err = queueBuffer(mLockedBuffer.get(), fd);
     ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
             mLockedBuffer->handle, strerror(-err));
 
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index c4e4efa..708888e 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -200,6 +200,52 @@
     return res;
 }
 
+status_t GraphicBuffer::lockAsync(uint32_t usage, void** vaddr, int fenceFd)
+{
+    const Rect lockBounds(width, height);
+    status_t res = lockAsync(usage, lockBounds, vaddr, fenceFd);
+    return res;
+}
+
+status_t GraphicBuffer::lockAsync(uint32_t usage, const Rect& rect, void** vaddr, int fenceFd)
+{
+    if (rect.left < 0 || rect.right  > this->width ||
+        rect.top  < 0 || rect.bottom > this->height) {
+        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
+                rect.left, rect.top, rect.right, rect.bottom,
+                this->width, this->height);
+        return BAD_VALUE;
+    }
+    status_t res = getBufferMapper().lockAsync(handle, usage, rect, vaddr, fenceFd);
+    return res;
+}
+
+status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, android_ycbcr *ycbcr, int fenceFd)
+{
+    const Rect lockBounds(width, height);
+    status_t res = lockAsyncYCbCr(usage, lockBounds, ycbcr, fenceFd);
+    return res;
+}
+
+status_t GraphicBuffer::lockAsyncYCbCr(uint32_t usage, const Rect& rect, android_ycbcr *ycbcr, int fenceFd)
+{
+    if (rect.left < 0 || rect.right  > this->width ||
+        rect.top  < 0 || rect.bottom > this->height) {
+        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
+                rect.left, rect.top, rect.right, rect.bottom,
+                this->width, this->height);
+        return BAD_VALUE;
+    }
+    status_t res = getBufferMapper().lockAsyncYCbCr(handle, usage, rect, ycbcr, fenceFd);
+    return res;
+}
+
+status_t GraphicBuffer::unlockAsync(int *fenceFd)
+{
+    status_t res = getBufferMapper().unlockAsync(handle, fenceFd);
+    return res;
+}
+
 size_t GraphicBuffer::getFlattenedSize() const {
     return (8 + (handle ? handle->numInts : 0))*sizeof(int);
 }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index a4cfce2..320b6c0 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,6 +20,8 @@
 #include <stdint.h>
 #include <errno.h>
 
+#include <sync/sync.h>
+
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
@@ -109,5 +111,65 @@
     return err;
 }
 
+status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
+        int usage, const Rect& bounds, void** vaddr, int fenceFd)
+{
+    ATRACE_CALL();
+    status_t err;
+
+    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
+        err = mAllocMod->lockAsync(mAllocMod, handle, usage,
+                bounds.left, bounds.top, bounds.width(), bounds.height(),
+                vaddr, fenceFd);
+    } else {
+        sync_wait(fenceFd, -1);
+        close(fenceFd);
+        err = mAllocMod->lock(mAllocMod, handle, usage,
+                bounds.left, bounds.top, bounds.width(), bounds.height(),
+                vaddr);
+    }
+
+    ALOGW_IF(err, "lockAsync(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
+        int usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
+{
+    ATRACE_CALL();
+    status_t err;
+
+    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
+        err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle, usage,
+                bounds.left, bounds.top, bounds.width(), bounds.height(),
+                ycbcr, fenceFd);
+    } else {
+        sync_wait(fenceFd, -1);
+        close(fenceFd);
+        err = mAllocMod->lock_ycbcr(mAllocMod, handle, usage,
+                bounds.left, bounds.top, bounds.width(), bounds.height(),
+                ycbcr);
+    }
+
+    ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
+status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
+{
+    ATRACE_CALL();
+    status_t err;
+
+    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
+        err = mAllocMod->unlockAsync(mAllocMod, handle, fenceFd);
+    } else {
+        *fenceFd = -1;
+        err = mAllocMod->unlock(mAllocMod, handle);
+    }
+
+    ALOGW_IF(err, "unlockAsync(...) failed %d (%s)", err, strerror(-err));
+    return err;
+}
+
 // ---------------------------------------------------------------------------
 }; // namespace android