Update ANativeWindow clients for sync

This change updates the uses of ANativeWindow to use the new ANW functions that
accept and return Sync HAL fence file descriptors.

Change-Id: I3ca648b6ac33f7360e86754f924aa072f95242f6
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 36a81a6..8195de9 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -23,6 +23,8 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
+#include <ui/Fence.h>
+
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceTexture.h>
@@ -62,11 +64,15 @@
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;
     ANativeWindow::cancelBuffer     = hook_cancelBuffer;
-    ANativeWindow::lockBuffer       = hook_lockBuffer;
     ANativeWindow::queueBuffer      = hook_queueBuffer;
     ANativeWindow::query            = hook_query;
     ANativeWindow::perform          = hook_perform;
 
+    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
+    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;
+    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;
+    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;
+
     const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
     const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
 
@@ -103,27 +109,54 @@
 }
 
 int SurfaceTextureClient::hook_dequeueBuffer(ANativeWindow* window,
-        ANativeWindowBuffer** buffer) {
+        ANativeWindowBuffer** buffer, int* fenceFd) {
     SurfaceTextureClient* c = getSelf(window);
-    return c->dequeueBuffer(buffer);
+    return c->dequeueBuffer(buffer, fenceFd);
 }
 
 int SurfaceTextureClient::hook_cancelBuffer(ANativeWindow* window,
-        ANativeWindowBuffer* buffer) {
+        ANativeWindowBuffer* buffer, int fenceFd) {
     SurfaceTextureClient* c = getSelf(window);
-    return c->cancelBuffer(buffer);
-}
-
-int SurfaceTextureClient::hook_lockBuffer(ANativeWindow* window,
-        ANativeWindowBuffer* buffer) {
-    SurfaceTextureClient* c = getSelf(window);
-    return c->lockBuffer(buffer);
+    return c->cancelBuffer(buffer, fenceFd);
 }
 
 int SurfaceTextureClient::hook_queueBuffer(ANativeWindow* window,
+        ANativeWindowBuffer* buffer, int fenceFd) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->queueBuffer(buffer, fenceFd);
+}
+
+int SurfaceTextureClient::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
+        ANativeWindowBuffer** buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    int fenceFd = -1;
+    int result = c->dequeueBuffer(buffer, &fenceFd);
+    sp<Fence> fence(new Fence(fenceFd));
+    int waitResult = fence->wait(Fence::TIMEOUT_NEVER);
+    if (waitResult != OK) {
+        ALOGE("hook_dequeueBuffer_DEPRECATED: Fence::wait returned an "
+                "error: %d", waitResult);
+        return waitResult;
+    }
+    return result;
+}
+
+int SurfaceTextureClient::hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
         ANativeWindowBuffer* buffer) {
     SurfaceTextureClient* c = getSelf(window);
-    return c->queueBuffer(buffer);
+    return c->cancelBuffer(buffer, -1);
+}
+
+int SurfaceTextureClient::hook_lockBuffer_DEPRECATED(ANativeWindow* window,
+        ANativeWindowBuffer* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->lockBuffer_DEPRECATED(buffer);
+}
+
+int SurfaceTextureClient::hook_queueBuffer_DEPRECATED(ANativeWindow* window,
+        ANativeWindowBuffer* buffer) {
+    SurfaceTextureClient* c = getSelf(window);
+    return c->queueBuffer(buffer, -1);
 }
 
 int SurfaceTextureClient::hook_query(const ANativeWindow* window,
@@ -157,7 +190,8 @@
     return res;
 }
 
-int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
+int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer,
+        int* fenceFd) {
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::dequeueBuffer");
     Mutex::Autolock lock(mMutex);
@@ -186,10 +220,11 @@
         }
     }
     *buffer = gbuf.get();
+    *fenceFd = -1;
     return OK;
 }
 
-int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) {
+int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer, int fenceFd) {
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::cancelBuffer");
     Mutex::Autolock lock(mMutex);
@@ -197,6 +232,12 @@
     if (i < 0) {
         return i;
     }
+    sp<Fence> fence(new Fence(fenceFd));
+    status_t err = fence->wait(Fence::TIMEOUT_NEVER);
+    if (err != OK) {
+        ALOGE("queueBuffer: Fence::wait returned an error: %d", err);
+        return err;
+    }
     mSurfaceTexture->cancelBuffer(i);
     return OK;
 }
@@ -214,13 +255,13 @@
     return BAD_VALUE;
 }
 
-int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
+int SurfaceTextureClient::lockBuffer_DEPRECATED(android_native_buffer_t* buffer) {
     ALOGV("SurfaceTextureClient::lockBuffer");
     Mutex::Autolock lock(mMutex);
     return OK;
 }
 
-int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
+int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
     ATRACE_CALL();
     ALOGV("SurfaceTextureClient::queueBuffer");
     Mutex::Autolock lock(mMutex);
@@ -237,6 +278,13 @@
         return i;
     }
 
+    sp<Fence> fence(new Fence(fenceFd));
+    status_t err = fence->wait(Fence::TIMEOUT_NEVER);
+    if (err != OK) {
+        ALOGE("queueBuffer: Fence::wait returned an error: %d", err);
+        return err;
+    }
+
     // Make sure the crop rectangle is entirely inside the buffer.
     Rect crop;
     mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
@@ -244,7 +292,7 @@
     ISurfaceTexture::QueueBufferOutput output;
     ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode,
             mTransform);
-    status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
+    err = mSurfaceTexture->queueBuffer(i, input, &output);
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
@@ -692,78 +740,83 @@
     }
 
     ANativeWindowBuffer* out;
-    status_t err = dequeueBuffer(&out);
+    int fenceFd = -1;
+    status_t err = dequeueBuffer(&out, &fenceFd);
     ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
     if (err == NO_ERROR) {
         sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
-        err = lockBuffer(backBuffer.get());
-        ALOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",
-                backBuffer->handle, strerror(-err));
-        if (err == NO_ERROR) {
-            const Rect bounds(backBuffer->width, backBuffer->height);
+        sp<Fence> fence(new Fence(fenceFd));
 
-            Region newDirtyRegion;
-            if (inOutDirtyBounds) {
-                newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
-                newDirtyRegion.andSelf(bounds);
-            } else {
-                newDirtyRegion.set(bounds);
-            }
-
-            // figure out if we can copy the frontbuffer back
-            const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
-            const bool canCopyBack = (frontBuffer != 0 &&
-                    backBuffer->width  == frontBuffer->width &&
-                    backBuffer->height == frontBuffer->height &&
-                    backBuffer->format == frontBuffer->format);
-
-            if (canCopyBack) {
-                // copy the area that is invalid and not repainted this round
-                const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
-                if (!copyback.isEmpty())
-                    copyBlt(backBuffer, frontBuffer, copyback);
-            } else {
-                // if we can't copy-back anything, modify the user's dirty
-                // region to make sure they redraw the whole buffer
-                newDirtyRegion.set(bounds);
-                mDirtyRegion.clear();
-                Mutex::Autolock lock(mMutex);
-                for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
-                    mSlots[i].dirtyRegion.clear();
-                }
-            }
-
-
-            { // scope for the lock
-                Mutex::Autolock lock(mMutex);
-                int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
-                if (backBufferSlot >= 0) {
-                    Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
-                    mDirtyRegion.subtract(dirtyRegion);
-                    dirtyRegion = newDirtyRegion;
-                }
-            }
-
-            mDirtyRegion.orSelf(newDirtyRegion);
-            if (inOutDirtyBounds) {
-                *inOutDirtyBounds = newDirtyRegion.getBounds();
-            }
-
-            void* vaddr;
-            status_t res = backBuffer->lock(
-                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
-                    newDirtyRegion.bounds(), &vaddr);
-
-            ALOGW_IF(res, "failed locking buffer (handle = %p)",
-                    backBuffer->handle);
-
-            mLockedBuffer = backBuffer;
-            outBuffer->width  = backBuffer->width;
-            outBuffer->height = backBuffer->height;
-            outBuffer->stride = backBuffer->stride;
-            outBuffer->format = backBuffer->format;
-            outBuffer->bits   = vaddr;
+        err = fence->wait(Fence::TIMEOUT_NEVER);
+        if (err != OK) {
+            ALOGE("Fence::wait failed (%s)", strerror(-err));
+            cancelBuffer(out, fenceFd);
+            return err;
         }
+
+        const Rect bounds(backBuffer->width, backBuffer->height);
+
+        Region newDirtyRegion;
+        if (inOutDirtyBounds) {
+            newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
+            newDirtyRegion.andSelf(bounds);
+        } else {
+            newDirtyRegion.set(bounds);
+        }
+
+        // figure out if we can copy the frontbuffer back
+        const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
+        const bool canCopyBack = (frontBuffer != 0 &&
+                backBuffer->width  == frontBuffer->width &&
+                backBuffer->height == frontBuffer->height &&
+                backBuffer->format == frontBuffer->format);
+
+        if (canCopyBack) {
+            // copy the area that is invalid and not repainted this round
+            const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
+            if (!copyback.isEmpty())
+                copyBlt(backBuffer, frontBuffer, copyback);
+        } else {
+            // if we can't copy-back anything, modify the user's dirty
+            // region to make sure they redraw the whole buffer
+            newDirtyRegion.set(bounds);
+            mDirtyRegion.clear();
+            Mutex::Autolock lock(mMutex);
+            for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
+                mSlots[i].dirtyRegion.clear();
+            }
+        }
+
+
+        { // scope for the lock
+            Mutex::Autolock lock(mMutex);
+            int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
+            if (backBufferSlot >= 0) {
+                Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
+                mDirtyRegion.subtract(dirtyRegion);
+                dirtyRegion = newDirtyRegion;
+            }
+        }
+
+        mDirtyRegion.orSelf(newDirtyRegion);
+        if (inOutDirtyBounds) {
+            *inOutDirtyBounds = newDirtyRegion.getBounds();
+        }
+
+        void* vaddr;
+        status_t res = backBuffer->lock(
+                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                newDirtyRegion.bounds(), &vaddr);
+
+        ALOGW_IF(res, "failed locking buffer (handle = %p)",
+                backBuffer->handle);
+
+        mLockedBuffer = backBuffer;
+        outBuffer->width  = backBuffer->width;
+        outBuffer->height = backBuffer->height;
+        outBuffer->stride = backBuffer->stride;
+        outBuffer->format = backBuffer->format;
+        outBuffer->bits   = vaddr;
     }
     return err;
 }
@@ -778,7 +831,7 @@
     status_t err = mLockedBuffer->unlock();
     ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
 
-    err = queueBuffer(mLockedBuffer.get());
+    err = queueBuffer(mLockedBuffer.get(), -1);
     ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
             mLockedBuffer->handle, strerror(-err));
 
diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk
index 3a8e356..e8863d3 100644
--- a/libs/gui/tests/Android.mk
+++ b/libs/gui/tests/Android.mk
@@ -2,14 +2,15 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := SurfaceTexture_test
+LOCAL_MODULE := libgui_test
 
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := \
-    Surface_test.cpp \
+    CpuConsumer_test.cpp \
     SurfaceTextureClient_test.cpp \
     SurfaceTexture_test.cpp \
+    Surface_test.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
 	libEGL \
@@ -18,35 +19,7 @@
 	libcutils \
 	libgui \
 	libstlport \
-	libui \
-	libutils \
-
-LOCAL_C_INCLUDES := \
-    bionic \
-    bionic/libstdc++/include \
-    external/gtest/include \
-    external/stlport/stlport \
-
-# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
-# to integrate with auto-test framework.
-include $(BUILD_NATIVE_TEST)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := CpuConsumer_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-    CpuConsumer_test.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libEGL \
-	libGLESv2 \
-	libbinder \
-	libcutils \
-	libgui \
-	libstlport \
+	libsync \
 	libui \
 	libutils \
 
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 7ad60e8..371fb8b 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -187,34 +187,7 @@
 }
 
 // Fill a YV12 buffer with a multi-colored checkerboard pattern
-void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
-    const int blockWidth = w > 16 ? w / 16 : 1;
-    const int blockHeight = h > 16 ? h / 16 : 1;
-    const int yuvTexOffsetY = 0;
-    int yuvTexStrideY = stride;
-    int yuvTexOffsetV = yuvTexStrideY * h;
-    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
-    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
-    int yuvTexStrideU = yuvTexStrideV;
-    for (int x = 0; x < w; x++) {
-        for (int y = 0; y < h; y++) {
-            int parityX = (x / blockWidth) & 1;
-            int parityY = (y / blockHeight) & 1;
-            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
-            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
-            if (x < w / 2 && y < h / 2) {
-                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
-                if (x * 2 < w / 2 && y * 2 < h / 2) {
-                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
-                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
-                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
-                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
-                        intensity;
-                }
-            }
-        }
-    }
-}
+void fillYV12Buffer(uint8_t* buf, int w, int h, int stride);
 
 // Fill a RAW sensor buffer with a multi-colored checkerboard pattern.
 // Assumes GRBG mosaic ordering. Result should be a grid in a 2x2 pattern
@@ -285,58 +258,13 @@
     checkPixel(buf, w-1, h-1, maxR, maxG, maxB);
 }
 
-// Fill a YV12 buffer with red outside a given rectangle and green inside it.
 void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
-        const android_native_rect_t& rect) {
-    const int yuvTexOffsetY = 0;
-    int yuvTexStrideY = stride;
-    int yuvTexOffsetV = yuvTexStrideY * h;
-    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
-    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
-    int yuvTexStrideU = yuvTexStrideV;
-    for (int x = 0; x < w; x++) {
-        for (int y = 0; y < h; y++) {
-            bool inside = rect.left <= x && x < rect.right &&
-                    rect.top <= y && y < rect.bottom;
-            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
-            if (x < w / 2 && y < h / 2) {
-                bool inside = rect.left <= 2*x && 2*x < rect.right &&
-                        rect.top <= 2*y && 2*y < rect.bottom;
-                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
-                buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
-                        inside ? 16 : 255;
-            }
-        }
-    }
-}
+        const android_native_rect_t& rect);
 
-void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
-    const size_t PIXEL_SIZE = 4;
-    for (int x = 0; x < w; x++) {
-        for (int y = 0; y < h; y++) {
-            off_t offset = (y * stride + x) * PIXEL_SIZE;
-            for (int c = 0; c < 4; c++) {
-                int parityX = (x / (1 << (c+2))) & 1;
-                int parityY = (y / (1 << (c+2))) & 1;
-                buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
-            }
-        }
-    }
-}
+void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride);
 
 void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
-        uint8_t g, uint8_t b, uint8_t a) {
-    const size_t PIXEL_SIZE = 4;
-    for (int y = 0; y < h; y++) {
-        for (int x = 0; x < h; x++) {
-            off_t offset = (y * stride + x) * PIXEL_SIZE;
-            buf[offset + 0] = r;
-            buf[offset + 1] = g;
-            buf[offset + 2] = b;
-            buf[offset + 3] = a;
-        }
-    }
-}
+        uint8_t g, uint8_t b, uint8_t a);
 
 // Configures the ANativeWindow producer-side interface based on test parameters
 void configureANW(const sp<ANativeWindow>& anw,
@@ -373,17 +301,13 @@
     status_t err;
     ANativeWindowBuffer* anb;
     ALOGVV("Dequeue buffer from %p", anw.get());
-    err = anw->dequeueBuffer(anw.get(), &anb);
+    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
     ASSERT_NO_ERROR(err, "dequeueBuffer error: ");
 
     ASSERT_TRUE(anb != NULL);
 
     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
 
-    ALOGVV("Lock buffer from %p", anw.get());
-    err = anw->lockBuffer(anw.get(), buf->getNativeBuffer());
-    ASSERT_NO_ERROR(err, "lockBuffer error: ");
-
     *stride = buf->getStride();
     uint8_t* img = NULL;
 
@@ -411,7 +335,7 @@
     ASSERT_NO_ERROR(err, "set_buffers_timestamp error: ");
 
     ALOGVV("Queue buffer to %p", anw.get());
-    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer());
+    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1);
     ASSERT_NO_ERROR(err, "queueBuffer error:");
 };
 
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 7d8dd33..59b9efd 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -180,129 +180,129 @@
 
 TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
     ANativeWindowBuffer* buf;
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(1, buf->width);
     EXPECT_EQ(1, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, PIXEL_FORMAT_RGB_565));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(16, buf->width);
     EXPECT_EQ(8, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(1, buf->width);
     EXPECT_EQ(1, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(16, buf->width);
     EXPECT_EQ(8, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(16, buf->width);
     EXPECT_EQ(8, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, 0));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(1, buf->width);
     EXPECT_EQ(1, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 0, 0, PIXEL_FORMAT_RGB_565));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(1, buf->width);
     EXPECT_EQ(1, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 16, 8, 0));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(16, buf->width);
     EXPECT_EQ(8, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
     sp<SurfaceTexture> st(mST);
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(16, buf->width);
     EXPECT_EQ(8, buf->height);
     EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf, -1));
 }
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
     ANativeWindowBuffer* buf[2];
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
     EXPECT_NE(buf[0], buf[1]);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
     EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
     EXPECT_NE(buf[0], buf[1]);
     EXPECT_EQ(16, buf[0]->width);
     EXPECT_EQ(16, buf[1]->width);
     EXPECT_EQ(8, buf[0]->height);
     EXPECT_EQ(8, buf[1]->height);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
 }
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
     ANativeWindowBuffer* buf[2];
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
     EXPECT_NE(buf[0], buf[1]);
     EXPECT_EQ(16, buf[0]->width);
     EXPECT_EQ(16, buf[1]->width);
     EXPECT_EQ(8, buf[0]->height);
     EXPECT_EQ(8, buf[1]->height);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
     EXPECT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 12, 24, 0));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
     EXPECT_NE(buf[0], buf[1]);
     EXPECT_EQ(12, buf[0]->width);
     EXPECT_EQ(12, buf[1]->width);
     EXPECT_EQ(24, buf[0]->height);
     EXPECT_EQ(24, buf[1]->height);
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[1], -1));
 }
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
@@ -310,18 +310,18 @@
     ASSERT_EQ(OK, mST->setSynchronousMode(false));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
 
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(OK, mST->updateTexImage());
 
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
 
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(OK, mST->updateTexImage());
@@ -332,15 +332,15 @@
     android_native_buffer_t* buf[3];
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
     EXPECT_NE(buf[0], buf[1]);
     EXPECT_NE(buf[1], buf[2]);
     EXPECT_NE(buf[2], buf[0]);
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
     EXPECT_EQ(OK, mST->updateTexImage());
@@ -353,19 +353,19 @@
     android_native_buffer_t* buf[3];
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
     EXPECT_NE(buf[0], buf[1]);
     EXPECT_NE(buf[1], buf[2]);
     EXPECT_NE(buf[2], buf[0]);
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
 }
@@ -375,20 +375,20 @@
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[0]);
 
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
     EXPECT_NE(buf[0], buf[1]);
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
 
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
     EXPECT_NE(buf[1], buf[2]);
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[2]);
 }
@@ -400,16 +400,16 @@
     android_native_buffer_t* firstBuf;
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &firstBuf));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), firstBuf);
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
     EXPECT_NE(buf[0], buf[1]);
     EXPECT_NE(buf[1], buf[2]);
     EXPECT_NE(buf[2], buf[0]);
@@ -422,24 +422,24 @@
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
     // We should be able to dequeue all the buffers before we've queued mANWy.
-    EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
-    EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
 
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
 
     EXPECT_EQ(OK, mST->updateTexImage());
     EXPECT_EQ(mST->getCurrentBuffer().get(), buf[1]);
 
-    EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
+    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
 
     // Once we've queued a buffer, however we should not be able to dequeue more
     // than (buffer-count - MIN_UNDEQUEUED_BUFFERS), which is 2 in this case.
-    EXPECT_EQ(-EBUSY, mANW->dequeueBuffer(mANW.get(), &buf[1]));
+    EXPECT_EQ(-EBUSY, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
 
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0]));
-    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2]));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[0], -1));
+    ASSERT_EQ(OK, mANW->cancelBuffer(mANW.get(), buf[2], -1));
 }
 
 TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) {
@@ -449,8 +449,8 @@
     ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 4, 4));
 
     android_native_buffer_t* buf;
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf, -1));
     ASSERT_EQ(OK, mST->updateTexImage());
 
     Rect crop = mST->getCurrentCrop();
@@ -500,20 +500,20 @@
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
     // dequeue/queue/update so we have a current buffer
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     mST->updateTexImage();
 
     MyThread* thread = new MyThread(mST);
     sp<Thread> threadBase(thread);
 
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     thread->run();
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[1]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1]));
-    //ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[2]));
-    //ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
+    //ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
+    //ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[2], -1));
     thread->bufferDequeued();
     thread->requestExitAndWait();
 }
@@ -522,8 +522,8 @@
     android_native_buffer_t* buf[3];
     float mtx[16] = {};
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     ASSERT_EQ(OK, mST->updateTexImage());
     mST->getTransformMatrix(mtx);
 
@@ -552,8 +552,8 @@
     android_native_buffer_t* buf[3];
     float mtx[16] = {};
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     ASSERT_EQ(OK, mST->updateTexImage());
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
     mST->getTransformMatrix(mtx);
@@ -590,9 +590,9 @@
 
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_set_buffers_geometry(mANW.get(), 8, 8, 0));
-    ASSERT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &crop));
-    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0]));
+    ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     ASSERT_EQ(OK, mST->updateTexImage());
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 6)); // frees buffers
     mST->getTransformMatrix(mtx);
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 078c17b..0060cf7 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -672,18 +672,19 @@
 // Calls to this function should be wrapped in an ASSERT_NO_FATAL_FAILURE().
 void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) {
     android_native_buffer_t* anb;
-    ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &anb));
+    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(),
+            &anb));
     ASSERT_TRUE(anb != NULL);
 
     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf->getNativeBuffer()));
 
     uint8_t* img = NULL;
     ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
             (void**)(&img)));
     fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride());
     ASSERT_EQ(NO_ERROR, buf->unlock());
-    ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer()));
+    ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer(),
+            -1));
 }
 
 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
@@ -696,18 +697,19 @@
             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     ANativeWindowBuffer* anb;
-    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+            &anb));
     ASSERT_TRUE(anb != NULL);
 
     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
 
     // Fill the buffer with the a checkerboard pattern
     uint8_t* img = NULL;
     buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
     fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
     buf->unlock();
-    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
+            -1));
 
     mST->updateTexImage();
 
@@ -741,18 +743,19 @@
             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     ANativeWindowBuffer* anb;
-    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+            &anb));
     ASSERT_TRUE(anb != NULL);
 
     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
 
     // Fill the buffer with the a checkerboard pattern
     uint8_t* img = NULL;
     buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
     fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
     buf->unlock();
-    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
+            -1));
 
     mST->updateTexImage();
 
@@ -801,19 +804,18 @@
         ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
 
         ANativeWindowBuffer* anb;
-        ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+                &anb));
         ASSERT_TRUE(anb != NULL);
 
         sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(),
-                buf->getNativeBuffer()));
 
         uint8_t* img = NULL;
         buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
         fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
         buf->unlock();
         ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
-                buf->getNativeBuffer()));
+                buf->getNativeBuffer(), -1));
 
         mST->updateTexImage();
 
@@ -877,7 +879,8 @@
         virtual bool threadLoop() {
             for (int i = 0; i < numFrames; i++) {
                 ANativeWindowBuffer* anb;
-                if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+                if (native_window_dequeue_buffer_and_wait(mANW.get(),
+                        &anb) != NO_ERROR) {
                     return false;
                 }
                 if (anb == NULL) {
@@ -885,10 +888,6 @@
                 }
 
                 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-                if (mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())
-                        != NO_ERROR) {
-                    return false;
-                }
 
                 const int yuvTexOffsetY = 0;
                 int stride = buf->getStride();
@@ -932,7 +931,7 @@
                 }
 
                 buf->unlock();
-                if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())
+                if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)
                         != NO_ERROR) {
                     return false;
                 }
@@ -1093,13 +1092,14 @@
 
             for (int numFrames =0 ; numFrames < 2; numFrames ++) {
 
-                if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+                if (native_window_dequeue_buffer_and_wait(mANW.get(),
+                        &anb) != NO_ERROR) {
                     return false;
                 }
                 if (anb == NULL) {
                     return false;
                 }
-                if (mANW->queueBuffer(mANW.get(), anb)
+                if (mANW->queueBuffer(mANW.get(), anb, -1)
                         != NO_ERROR) {
                     return false;
                 }
@@ -1147,11 +1147,11 @@
 
     ANativeWindowBuffer *anb;
 
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
 
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
 
     EXPECT_EQ(OK,mST->updateTexImage());
     EXPECT_EQ(OK,mST->updateTexImage());
@@ -1163,8 +1163,8 @@
 
     ASSERT_EQ(OK, mST->setSynchronousMode(true));
 
-    EXPECT_EQ(OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
 
     // Will fail here if mCurrentTexture is not cleared properly
     mFW->waitForFrame();
@@ -1193,8 +1193,8 @@
 
     android_native_rect_t odd = {23, 78, 123, 477};
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd));
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
     mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     Rect r = mST->getCurrentCrop();
@@ -1227,8 +1227,8 @@
     // The crop is in the shape of (320, 180) === 16 x 9
     android_native_rect_t standard = {10, 20, 330, 200};
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard));
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
     mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     Rect r = mST->getCurrentCrop();
@@ -1238,8 +1238,8 @@
     // make this wider then desired aspect 239 x 100 (2.39:1)
     android_native_rect_t wide = {20, 30, 259, 130};
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide));
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
     mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     r = mST->getCurrentCrop();
@@ -1250,8 +1250,8 @@
     // This image is taller then desired aspect 400 x 300 (4:3)
     android_native_rect_t narrow = {0, 0, 400, 300};
     ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow));
-    EXPECT_EQ (OK, mANW->dequeueBuffer(mANW.get(), &anb));
-    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
+    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
     mFW->waitForFrame();
     EXPECT_EQ(OK,mST->updateTexImage());
     r = mST->getCurrentCrop();
@@ -1278,31 +1278,34 @@
             ANativeWindowBuffer* anb;
 
             // Frame 1
-            if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+            if (native_window_dequeue_buffer_and_wait(mANW.get(),
+                    &anb) != NO_ERROR) {
                 return false;
             }
             if (anb == NULL) {
                 return false;
             }
-            if (mANW->queueBuffer(mANW.get(), anb)
+            if (mANW->queueBuffer(mANW.get(), anb, -1)
                     != NO_ERROR) {
                 return false;
             }
 
             // Frame 2
-            if (mANW->dequeueBuffer(mANW.get(), &anb) != NO_ERROR) {
+            if (native_window_dequeue_buffer_and_wait(mANW.get(),
+                    &anb) != NO_ERROR) {
                 return false;
             }
             if (anb == NULL) {
                 return false;
             }
-            if (mANW->queueBuffer(mANW.get(), anb)
+            if (mANW->queueBuffer(mANW.get(), anb, -1)
                     != NO_ERROR) {
                 return false;
             }
 
             // Frame 3 - error expected
-            mDequeueError = mANW->dequeueBuffer(mANW.get(), &anb);
+            mDequeueError = native_window_dequeue_buffer_and_wait(mANW.get(),
+                &anb);
             return false;
         }
 
@@ -1346,26 +1349,29 @@
 
     // make sure it works with small textures
     mST->setDefaultBufferSize(16, texHeight);
-    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+            &anb));
     EXPECT_EQ(16, anb->width);
     EXPECT_EQ(texHeight, anb->height);
-    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
     EXPECT_EQ(NO_ERROR, mST->updateTexImage());
 
     // make sure it works with GL_MAX_TEXTURE_SIZE
     mST->setDefaultBufferSize(maxTextureSize, texHeight);
-    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+            &anb));
     EXPECT_EQ(maxTextureSize, anb->width);
     EXPECT_EQ(texHeight, anb->height);
-    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
     EXPECT_EQ(NO_ERROR, mST->updateTexImage());
 
     // make sure it fails with GL_MAX_TEXTURE_SIZE+1
     mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
-    EXPECT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+            &anb));
     EXPECT_EQ(maxTextureSize+1, anb->width);
     EXPECT_EQ(texHeight, anb->height);
-    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb));
+    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
     ASSERT_NE(NO_ERROR, mST->updateTexImage());
 }
 
@@ -2134,11 +2140,11 @@
             GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     android_native_buffer_t* anb;
-    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+            &anb));
     ASSERT_TRUE(anb != NULL);
 
     sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
 
     // Fill the buffer with green
     uint8_t* img = NULL;
@@ -2146,7 +2152,8 @@
     fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255,
             0, 255);
     buf->unlock();
-    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
+            -1));
 
     ASSERT_EQ(NO_ERROR, mST->updateTexImage());
 
@@ -2157,12 +2164,11 @@
     for (int i = 0; i < 4; i++) {
         SCOPED_TRACE(String8::format("frame %d", i).string());
 
-        ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
+                &anb));
         ASSERT_TRUE(anb != NULL);
 
         buf = new GraphicBuffer(anb, false);
-        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(),
-                buf->getNativeBuffer()));
 
         // Fill the buffer with red
         ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -2171,7 +2177,7 @@
                 0, 255);
         ASSERT_EQ(NO_ERROR, buf->unlock());
         ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
-                buf->getNativeBuffer()));
+                buf->getNativeBuffer(), -1));
 
         ASSERT_EQ(NO_ERROR, mST->updateTexImage());
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index b585d68..5046bf5 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -97,22 +97,23 @@
     ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(anw.get(), 3));
     ANativeWindowBuffer* buf = 0;
 
-    status_t err = anw->dequeueBuffer(anw.get(), &buf);
+    status_t err = native_window_dequeue_buffer_and_wait(anw.get(), &buf);
     if (err) {
         // we could fail if GRALLOC_USAGE_PROTECTED is not supported.
         // that's okay as long as this is the reason for the failure.
         // try again without the GRALLOC_USAGE_PROTECTED bit.
         ASSERT_EQ(NO_ERROR, native_window_set_usage(anw.get(), 0));
-        ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
+        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(),
+                &buf));
         return;
     }
-    ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf));
+    ASSERT_EQ(NO_ERROR, anw->cancelBuffer(anw.get(), buf, -1));
 
     for (int i = 0; i < 4; i++) {
         // Loop to make sure SurfaceFlinger has retired a protected buffer.
-        ASSERT_EQ(NO_ERROR, anw->dequeueBuffer(anw.get(), &buf));
-        ASSERT_EQ(NO_ERROR, anw->lockBuffer(anw.get(), buf));
-        ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf));
+        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(),
+                &buf));
+        ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
     }
     heap = 0;
     w = h = fmt = 0;
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 5aff7a4..80c28a1 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -16,6 +16,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+	Fence.cpp \
 	FramebufferNativeWindow.cpp \
 	GraphicBuffer.cpp \
 	GraphicBufferAllocator.cpp \
@@ -26,8 +27,9 @@
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
-	libutils \
-	libhardware
+	libhardware \
+	libsync \
+	libutils
 
 ifneq ($(BOARD_FRAMEBUFFER_FORCE_FORMAT),)
 LOCAL_CFLAGS += -DFRAMEBUFFER_FORCE_FORMAT=$(BOARD_FRAMEBUFFER_FORCE_FORMAT)
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index dec99b6..84cb8f3 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -28,6 +28,7 @@
 #include <utils/RefBase.h>
 
 #include <ui/ANativeObjectBase.h>
+#include <ui/Fence.h>
 #include <ui/FramebufferNativeWindow.h>
 #include <ui/Rect.h>
 
@@ -145,10 +146,13 @@
 
     ANativeWindow::setSwapInterval = setSwapInterval;
     ANativeWindow::dequeueBuffer = dequeueBuffer;
-    ANativeWindow::lockBuffer = lockBuffer;
     ANativeWindow::queueBuffer = queueBuffer;
     ANativeWindow::query = query;
     ANativeWindow::perform = perform;
+
+    ANativeWindow::dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED;
+    ANativeWindow::lockBuffer_DEPRECATED = lockBuffer_DEPRECATED;
+    ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED;
 }
 
 FramebufferNativeWindow::~FramebufferNativeWindow() 
@@ -207,9 +211,24 @@
     return index;
 }
 
-int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, 
+int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window, 
         ANativeWindowBuffer** buffer)
 {
+    int fenceFd = -1;
+    int result = dequeueBuffer(window, buffer, &fenceFd);
+    sp<Fence> fence(new Fence(fenceFd));
+    int waitResult = fence->wait(Fence::TIMEOUT_NEVER);
+    if (waitResult != OK) {
+        ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an "
+                "error: %d", waitResult);
+        return waitResult;
+    }
+    return result;
+}
+
+int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window, 
+        ANativeWindowBuffer** buffer, int* fenceFd)
+{
     FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
     framebuffer_device_t* fb = self->fbDev;
@@ -227,13 +246,15 @@
     self->mCurrentBufferIndex = index;
 
     *buffer = self->buffers[index].get();
+    *fenceFd = -1;
 
     return 0;
 }
 
-int FramebufferNativeWindow::lockBuffer(ANativeWindow* window, 
+int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* window, 
         ANativeWindowBuffer* buffer)
 {
+    // XXX: Can this code all get ripped out?  Should it move to dequeueBuffer?
     FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
 
@@ -247,14 +268,23 @@
     return NO_ERROR;
 }
 
-int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 
+int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window, 
         ANativeWindowBuffer* buffer)
 {
+    return queueBuffer(window, buffer, -1);
+}
+
+int FramebufferNativeWindow::queueBuffer(ANativeWindow* window, 
+        ANativeWindowBuffer* buffer, int fenceFd)
+{
     FramebufferNativeWindow* self = getSelf(window);
     Mutex::Autolock _l(self->mutex);
     framebuffer_device_t* fb = self->fbDev;
     buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
 
+    sp<Fence> fence(new Fence(fenceFd));
+    fence->wait(Fence::TIMEOUT_NEVER);
+
     const int index = self->mCurrentBufferIndex;
     int res = fb->post(fb, handle);
     self->front = static_cast<NativeBuffer*>(buffer);