Merge changes from topics 'USAGE_IO_INPUT', 'USAGE_IO_OUTPUT'

* changes:
  Update C++ API (libRSCpp.so) with the corresponding AllocationGetSurface driver implementation change
  Implement USAGE_IO_INPUT related functions on top of NDK.
  Implement USAGE_IO_OUTPUT related methods on top of NDK.
diff --git a/Android.mk b/Android.mk
index 7c32525..3e5f593 100644
--- a/Android.mk
+++ b/Android.mk
@@ -64,7 +64,7 @@
 
 LOCAL_SHARED_LIBRARIES += libRS_internal libRSCpuRef
 LOCAL_SHARED_LIBRARIES += liblog libutils libEGL libGLESv1_CM libGLESv2
-LOCAL_SHARED_LIBRARIES += libui libgui
+LOCAL_SHARED_LIBRARIES += libui libgui libandroid
 
 LOCAL_SHARED_LIBRARIES += libbcinfo
 
@@ -188,7 +188,9 @@
 LOCAL_SHARED_LIBRARIES += libdl libgui libui
 LOCAL_SHARED_LIBRARIES += libft2 libpng
 
-LOCAL_SHARED_LIBRARIES += libbcinfo
+LOCAL_SHARED_LIBRARIES += libbcinfo libmediandk
+
+LOCAL_C_INCLUDES += frameworks/av/include/ndk
 
 LOCAL_CFLAGS += $(rs_base_CFLAGS)
 
diff --git a/cpp/Allocation.cpp b/cpp/Allocation.cpp
index 12dad8f..2f5ca64 100644
--- a/cpp/Allocation.cpp
+++ b/cpp/Allocation.cpp
@@ -501,12 +501,10 @@
         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only get Surface if IO_INPUT usage specified.");
         return nullptr;
     }
-    IGraphicBufferProducer *v = (IGraphicBufferProducer *)RS::dispatch->AllocationGetSurface(mRS->getContext(),
-                                                                                             getID());
-    android::sp<IGraphicBufferProducer> bp = v;
-    v->decStrong(nullptr);
-
-    return new Surface(bp, true);;
+    ANativeWindow *anw = (ANativeWindow *)RS::dispatch->AllocationGetSurface(mRS->getContext(),
+                                                                             getID());
+    sp<Surface> surface(static_cast<Surface*>(anw));
+    return surface;
 }
 
 void Allocation::setSurface(const sp<Surface>& s) {
diff --git a/driver/rsdAllocation.cpp b/driver/rsdAllocation.cpp
index 249daa5..0381715 100644
--- a/driver/rsdAllocation.cpp
+++ b/driver/rsdAllocation.cpp
@@ -14,16 +14,10 @@
  * limitations under the License.
  */
 
-#include "rsdCore.h"
 #include "rsdAllocation.h"
+#include "rsdCore.h"
 
-#include "rsAllocation.h"
-
-#ifndef RS_COMPATIBILITY_LIB
-#include "system/window.h"
-#include "ui/Rect.h"
-#include "ui/GraphicBufferMapper.h"
-#endif
+#include <android/native_window.h>
 
 #ifdef RS_COMPATIBILITY_LIB
 #include "rsCompatibilityLib.h"
@@ -39,12 +33,6 @@
 #include <GLES/glext.h>
 #endif
 
-#ifndef RS_COMPATIBILITY_LIB
-using android::GraphicBufferMapper;
-using android::PIXEL_FORMAT_RGBA_8888;
-using android::Rect;
-#endif
-
 using android::renderscript::Allocation;
 using android::renderscript::Context;
 using android::renderscript::Element;
@@ -582,17 +570,13 @@
 
         if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
             (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
-
-            DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
             ANativeWindow *nw = drv->wndSurface;
             if (nw) {
-                GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-                mapper.unlock(drv->wndBuffer->handle);
-                int32_t r = nw->cancelBuffer(nw, drv->wndBuffer, -1);
-
+                //If we have an attached surface, need to release it.
+                ANativeWindow_unlockAndPost(nw);
+                ANativeWindow_release(nw);
                 drv->wndSurface = nullptr;
-                native_window_api_disconnect(nw, NATIVE_WINDOW_API_CPU);
-                nw->decStrong(nullptr);
+                delete drv->wndBuffer;
             }
         }
 #endif
@@ -717,21 +701,17 @@
 #ifndef RS_COMPATIBILITY_LIB
 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
-
-    int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer);
+    // Must lock the whole surface
+    if(drv->wndBuffer == nullptr) {
+        drv->wndBuffer = new ANativeWindow_Buffer;
+    }
+    int32_t r = ANativeWindow_lock(nw, drv->wndBuffer, NULL);
     if (r) {
-        rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer.");
+        rsc->setError(RS_ERROR_DRIVER, "Error Locking IO output buffer.");
         return false;
     }
 
-    // Must lock the whole surface
-    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-    Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height);
-
-    void *dst = nullptr;
-    mapper.lock(drv->wndBuffer->handle,
-            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
-            bounds, &dst);
+    void *dst = drv->wndBuffer->bits;
     alloc->mHal.drvState.lod[0].mallocPtr = dst;
     alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
     rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0);
@@ -743,75 +723,23 @@
 void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
 #ifndef RS_COMPATIBILITY_LIB
     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
-    ANativeWindow *old = drv->wndSurface;
-
-    if (nw) {
-        nw->incStrong(nullptr);
-    }
-
-    if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
-        //TODO finish support for render target + script
-        drv->wnd = nw;
-        return;
-    }
 
     // Cleanup old surface if there is one.
     if (drv->wndSurface) {
         ANativeWindow *old = drv->wndSurface;
-        GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-        mapper.unlock(drv->wndBuffer->handle);
-        old->cancelBuffer(old, drv->wndBuffer, -1);
+        ANativeWindow_unlockAndPost(old);
+        ANativeWindow_release(old);
         drv->wndSurface = nullptr;
-
-        native_window_api_disconnect(old, NATIVE_WINDOW_API_CPU);
-        old->decStrong(nullptr);
     }
 
-    if (nw != nullptr) {
+    if (nw) {
         int32_t r;
-        uint32_t flags = 0;
-
-        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
-            flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
-        }
-        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
-            flags |= GRALLOC_USAGE_HW_RENDER;
-        }
-
-        r = native_window_api_connect(nw, NATIVE_WINDOW_API_CPU);
+        r = ANativeWindow_setBuffersGeometry(nw, alloc->mHal.drvState.lod[0].dimX,
+                                                 alloc->mHal.drvState.lod[0].dimY,
+                                                 WINDOW_FORMAT_RGBA_8888);
         if (r) {
-            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
-            goto error;
-        }
-
-        r = native_window_set_usage(nw, flags);
-        if (r) {
-            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
-            goto error;
-        }
-
-        r = native_window_set_buffers_dimensions(nw, alloc->mHal.drvState.lod[0].dimX,
-                                                 alloc->mHal.drvState.lod[0].dimY);
-        if (r) {
-            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions.");
-            goto error;
-        }
-
-        int format = 0;
-        const Element *e = alloc->mHal.state.type->getElement();
-        if ((e->getType() != RS_TYPE_UNSIGNED_8) ||
-            (e->getVectorSize() != 4)) {
-            // We do not check for RGBA, RGBx, to allow for interop with U8_4
-
-            rsc->setError(RS_ERROR_DRIVER, "Surface passed to setSurface is not U8_4, RGBA.");
-            goto error;
-        }
-        format = PIXEL_FORMAT_RGBA_8888;
-
-        r = native_window_set_buffers_format(nw, format);
-        if (r) {
-            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer format.");
-            goto error;
+            rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer geometry.");
+            return;
         }
 
         IoGetBuffer(rsc, alloc, nw);
@@ -819,14 +747,6 @@
     }
 
     return;
-
- error:
-
-    if (nw) {
-        nw->decStrong(nullptr);
-    }
-
-
 #endif
 }
 
@@ -841,14 +761,11 @@
     }
     if (nw) {
         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
-            GraphicBufferMapper &mapper = GraphicBufferMapper::get();
-            mapper.unlock(drv->wndBuffer->handle);
-            int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
+            int32_t r = ANativeWindow_unlockAndPost(nw);
             if (r) {
                 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
                 return;
             }
-
             IoGetBuffer(rsc, alloc, nw);
         }
     } else {
diff --git a/driver/rsdAllocation.h b/driver/rsdAllocation.h
index ec31aed..c2d1467 100644
--- a/driver/rsdAllocation.h
+++ b/driver/rsdAllocation.h
@@ -53,15 +53,14 @@
     GLenum glType;
     GLenum glFormat;
 
-    ANativeWindowBuffer *wndBuffer;
     android::GLConsumer *surfaceTexture;
 #else
     int glTarget;
     int glType;
     int glFormat;
+#endif
 
     ANativeWindow_Buffer *wndBuffer;
-#endif
 
     bool useUserProvidedPtr;
     bool uploadDeferred;
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 980850c..59944bf 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -18,6 +18,10 @@
 #include "rsAllocation.h"
 #include "rs_hal.h"
 
+#ifndef RS_COMPATIBILITY_LIB
+#include "rsGrallocConsumer.h"
+#endif
+
 namespace android {
 namespace renderscript {
 
@@ -148,8 +152,11 @@
 
 Allocation::~Allocation() {
 #ifndef RS_COMPATIBILITY_LIB
-    if (mGrallocConsumer.get()) {
+    if (mGrallocConsumer) {
         mGrallocConsumer->releaseIdx(mCurrentIdx);
+        if (!mGrallocConsumer->isActive()) {
+            delete mGrallocConsumer;
+        }
         mGrallocConsumer = nullptr;
     }
 #endif
@@ -569,29 +576,6 @@
     rsc->setError(RS_ERROR_FATAL_DRIVER, "resize2d not implemented");
 }
 
-#ifndef RS_COMPATIBILITY_LIB
-Allocation::NewBufferListener::NewBufferListener(uint32_t numAlloc) {
-    alloc = new const Allocation *[numAlloc];
-    mNumAlloc = numAlloc;
-    for (uint32_t i = 0; i < numAlloc; i++) {
-        alloc[i] = nullptr;
-    }
-}
-
-Allocation::NewBufferListener::~NewBufferListener() {
-    delete[] alloc;
-}
-
-void Allocation::NewBufferListener::onFrameAvailable(const BufferItem& /* item */) {
-    for (uint32_t i = 0; i < mNumAlloc; i++) {
-        if (alloc[i] != nullptr) {
-            intptr_t ip = (intptr_t)alloc[i];
-            rsc->sendMessageToClient(&ip, RS_MESSAGE_TO_CLIENT_NEW_BUFFER, 0, sizeof(ip), true);
-        }
-    }
-}
-#endif
-
 void Allocation::setupGrallocConsumer(const Context *rsc, uint32_t numAlloc) {
 #ifndef RS_COMPATIBILITY_LIB
     // Configure GrallocConsumer to be in asynchronous mode
@@ -599,17 +583,9 @@
         rsc->setError(RS_ERROR_FATAL_DRIVER, "resize2d not implemented");
         return;
     }
-    sp<IGraphicBufferConsumer> bc;
-    BufferQueue::createBufferQueue(&mGraphicBufferProducer, &bc);
-    mGrallocConsumer = new GrallocConsumer(this, bc, mHal.drvState.grallocFlags, numAlloc);
-
-    mBufferListener = new NewBufferListener(numAlloc);
-    mBufferListener->rsc = rsc;
-    mBufferListener->alloc[0] = this;
+    mGrallocConsumer = new GrallocConsumer(rsc, this, numAlloc);
     mCurrentIdx = 0;
     mBufferQueueInited = true;
-
-    mGrallocConsumer->setFrameAvailableListener(mBufferListener);
 #endif
 }
 
@@ -622,12 +598,10 @@
         // multi-frame case.
         setupGrallocConsumer(rsc, 1);
     }
-    mGraphicBufferProducer->incStrong(nullptr);
-    return mGraphicBufferProducer.get();
+    return mGrallocConsumer->getNativeWindow();
 #else
     return nullptr;
 #endif
-    //return rsc->mHal.funcs.allocation.getSurface(rsc, this);
 }
 
 void Allocation::shareBufferQueue(const Context *rsc, const Allocation *alloc) {
@@ -638,10 +612,6 @@
         rsc->setError(RS_ERROR_DRIVER, "Maximum allocations attached to a BufferQueue");
         return;
     }
-
-    mGraphicBufferProducer = alloc->mGraphicBufferProducer;
-    mBufferListener = alloc->mBufferListener;
-    mBufferListener->alloc[mCurrentIdx] = this;
     mBufferQueueInited = true;
 #endif
 }
@@ -661,11 +631,11 @@
     size_t stride = 0;
 #ifndef RS_COMPATIBILITY_LIB
     if (mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
-        status_t ret = mGrallocConsumer->lockNextBuffer(mCurrentIdx);
+        media_status_t ret = mGrallocConsumer->lockNextBuffer(mCurrentIdx);
 
-        if (ret == OK) {
+        if (ret == AMEDIA_OK) {
             rsc->mHal.funcs.allocation.ioReceive(rsc, this);
-        } else if (ret == BAD_VALUE) {
+        } else if (ret == AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE) {
             // No new frame, don't do anything
         } else {
             rsc->setError(RS_ERROR_DRIVER, "Error receiving IO input buffer.");
diff --git a/rsAllocation.h b/rsAllocation.h
index f6a1283..60f17a3 100644
--- a/rsAllocation.h
+++ b/rsAllocation.h
@@ -20,7 +20,6 @@
 #include "rsType.h"
 
 #ifndef RS_COMPATIBILITY_LIB
-#include "rsGrallocConsumer.h"
 #include "gui/CpuConsumer.h"
 #include "gui/GLConsumer.h"
 #else
@@ -33,6 +32,7 @@
 namespace renderscript {
 
 class Program;
+class GrallocConsumer;
 
 /*****************************************************************************
  * CAUTION
@@ -220,21 +220,7 @@
     }
 
 #ifndef RS_COMPATIBILITY_LIB
-    class NewBufferListener : public android::ConsumerBase::FrameAvailableListener {
-    public:
-        explicit NewBufferListener(uint32_t numAlloc);
-        virtual ~NewBufferListener();
-        const android::renderscript::Context *rsc;
-        const android::renderscript::Allocation **alloc;
-
-        virtual void onFrameAvailable(const BufferItem& item);
-    private:
-        uint32_t mNumAlloc;
-    };
-
-    sp<NewBufferListener> mBufferListener;
-    sp< GrallocConsumer > mGrallocConsumer;
-    sp<IGraphicBufferProducer> mGraphicBufferProducer;
+    GrallocConsumer *mGrallocConsumer = nullptr;
     bool mBufferQueueInited = false;
     uint32_t mCurrentIdx;
 #endif
diff --git a/rsGrallocConsumer.cpp b/rsGrallocConsumer.cpp
index 77bffa5..67ab9d0 100644
--- a/rsGrallocConsumer.cpp
+++ b/rsGrallocConsumer.cpp
@@ -14,24 +14,17 @@
  * limitations under the License.
  */
 
-#define ATRACE_TAG ATRACE_TAG_RS
-
-#include "rsContext.h"
 #include "rsAllocation.h"
-#include "rs_hal.h"
-
-#include <utils/Log.h>
+#include "rsContext.h"
 #include "rsGrallocConsumer.h"
-#include <gui/BufferItem.h>
-#include <ui/GraphicBuffer.h>
-
+#include "rs_hal.h"
 
 namespace android {
 namespace renderscript {
 
-GrallocConsumer::GrallocConsumer(Allocation *a, const sp<IGraphicBufferConsumer>& bq, int flags, uint32_t numAlloc) :
-    ConsumerBase(bq, true)
+GrallocConsumer::GrallocConsumer (const Context *rsc, Allocation *a, uint32_t numAlloc)
 {
+    mCtx = rsc;
     mAlloc = new Allocation *[numAlloc];
     mAcquiredBuffer = new AcquiredBuffer[numAlloc];
     isIdxUsed = new bool[numAlloc];
@@ -39,236 +32,207 @@
     mAlloc[0] = a;
     isIdxUsed[0] = true;
     mNumAlloc = numAlloc;
-    if (flags == 0) {
-        flags = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_RENDERSCRIPT;
-    } else {
-        flags |= GRALLOC_USAGE_RENDERSCRIPT;
-    }
-    mConsumer->setConsumerUsageBits(flags);
-    mConsumer->setMaxAcquiredBufferCount(numAlloc + 1);
 
-    uint32_t y = a->mHal.drvState.lod[0].dimY;
-    if (y < 1) y = 1;
-    mConsumer->setDefaultBufferSize(a->mHal.drvState.lod[0].dimX, y);
+    uint32_t width  = a->mHal.drvState.lod[0].dimX;
+    uint32_t height = a->mHal.drvState.lod[0].dimY;
+    if (height < 1) height = 1;
 
+    int32_t format = AIMAGE_FORMAT_RGBA_8888;
     if (a->mHal.state.yuv) {
-        bq->setDefaultBufferFormat(a->mHal.state.yuv);
+        format = AIMAGE_FORMAT_YUV_420_888;
     }
+
+    media_status_t ret = AImageReader_new(
+            width, height, format,
+            mNumAlloc, &mImgReader);
+    if (ret != AMEDIA_OK || mImgReader == nullptr) {
+        ALOGE("Error creating image reader. ret %d", ret);
+    }
+
+    ret = AImageReader_getWindow(mImgReader, &mNativeWindow);
+    if (ret != AMEDIA_OK || mNativeWindow == nullptr) {
+        ALOGE("Error creating native window. ret %d", ret);
+    }
+
+    mReaderCb = {this, GrallocConsumer::onFrameAvailable};
+    ret = AImageReader_setImageListener(mImgReader, &mReaderCb);
+
     for (uint32_t i = 1; i < numAlloc; i++) {
         isIdxUsed[i] = false;
     }
-    //mBufferQueue->setConsumerName(name);
 }
 
 GrallocConsumer::~GrallocConsumer() {
+    AImageReader_delete(mImgReader);
     delete[] mAlloc;
     delete[] mAcquiredBuffer;
     delete[] isIdxUsed;
 }
 
+void GrallocConsumer::onFrameAvailable(void* obj, AImageReader* reader) {
+    GrallocConsumer* consumer = (GrallocConsumer *) obj;
+    for (uint32_t i = 0; i < consumer->mNumAlloc; i++) {
+        if (consumer->mAlloc[i] != nullptr) {
+            intptr_t ip = (intptr_t)(consumer->mAlloc[i]);
+            consumer->mCtx->sendMessageToClient(&ip,
+                RS_MESSAGE_TO_CLIENT_NEW_BUFFER, 0, sizeof(ip), true);
+        }
+    }
+}
 
+ANativeWindow* GrallocConsumer::getNativeWindow() {
+    return mNativeWindow;
+}
 
-status_t GrallocConsumer::lockNextBuffer(uint32_t idx) {
-    Mutex::Autolock _l(mMutex);
-    status_t err;
+media_status_t GrallocConsumer::lockNextBuffer(uint32_t idx) {
+    media_status_t ret;
 
     if (idx >= mNumAlloc) {
         ALOGE("Invalid buffer index: %d", idx);
-        return BAD_VALUE;
+        return AMEDIA_ERROR_INVALID_PARAMETER;
     }
 
-    if (mAcquiredBuffer[idx].mSlot != BufferQueue::INVALID_BUFFER_SLOT) {
-        err = releaseAcquiredBufferLocked(idx);
-        if (err) {
-            return err;
+    if (mAcquiredBuffer[idx].mImg != nullptr) {
+        ret = unlockBuffer(idx);
+        if (ret != AMEDIA_OK) {
+            return ret;
         }
     }
 
-    BufferItem b;
-
-    err = acquireBufferLocked(&b, 0);
-    if (err != OK) {
-        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-            return BAD_VALUE;
-        } else {
-            ALOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
-            return err;
-        }
+    ret = AImageReader_acquireNextImage(mImgReader, &(mAcquiredBuffer[idx].mImg));
+    if (ret != AMEDIA_OK || mAcquiredBuffer[idx].mImg == nullptr) {
+        ALOGE("%s: acquire image from reader %p failed! ret: %d, img %p",
+                __FUNCTION__, mImgReader, ret, mAcquiredBuffer[idx].mImg);
+        return ret;
     }
 
-    int slot = b.mSlot;
-
-    if (b.mFence.get()) {
-        err = b.mFence->waitForever("GrallocConsumer::lockNextBuffer");
-        if (err != OK) {
-            ALOGE("Failed to wait for fence of acquired buffer: %s (%d)",
-                    strerror(-err), err);
-            return err;
-        }
+    AImage *img = mAcquiredBuffer[idx].mImg;
+    int32_t format = -1;
+    ret = AImage_getFormat(img, &format);
+    if (ret != AMEDIA_OK || format == -1) {
+        ALOGE("%s: get format for image %p failed! ret: %d, format %d",
+                 __FUNCTION__, img, ret, format);
+        return ret;
     }
 
-    void *bufferPointer = nullptr;
-    android_ycbcr ycbcr = android_ycbcr();
-
-    if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
-            HAL_PIXEL_FORMAT_YCbCr_420_888) {
-        err = mSlots[slot].mGraphicBuffer->lockYCbCr(
-            GraphicBuffer::USAGE_SW_READ_OFTEN,
-            b.mCrop,
-            &ycbcr);
-
-        if (err != OK) {
-            ALOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
-                    strerror(-err), err);
-            return err;
-        }
-        bufferPointer = ycbcr.y;
-    } else {
-        err = mSlots[slot].mGraphicBuffer->lock(
-            GraphicBuffer::USAGE_SW_READ_OFTEN,
-            b.mCrop,
-            &bufferPointer);
-
-        if (err != OK) {
-            ALOGE("Unable to lock buffer for CPU reading: %s (%d)",
-                    strerror(-err), err);
-            return err;
-        }
+    if (format != AIMAGE_FORMAT_YUV_420_888 && format != AIMAGE_FORMAT_RGBA_8888) {
+        ALOGE("Format %d not supported", format);
+        return AMEDIA_ERROR_INVALID_OBJECT;
     }
 
-    size_t lockedIdx = 0;
-    rsAssert(mAcquiredBuffer[idx].mSlot == BufferQueue::INVALID_BUFFER_SLOT);
+    uint8_t *data = nullptr;
+    int dataLength = 0;
+    ret =  AImage_getPlaneData(img, 0, &data, &dataLength);
+    if (ret != AMEDIA_OK || data == nullptr || dataLength <= 0) {
+        ALOGE("%s: get data for image %p failed! ret: %d, data %p, len %d",
+                __FUNCTION__, img, ret, data, dataLength);
+        return ret;
+    }
 
-    mAcquiredBuffer[idx].mSlot = slot;
-    mAcquiredBuffer[idx].mBufferPointer = bufferPointer;
-    mAcquiredBuffer[idx].mGraphicBuffer = mSlots[slot].mGraphicBuffer;
+    int64_t timestamp = -1;
+    ret = AImage_getTimestamp(img, &timestamp);
+    if (ret != AMEDIA_OK || timestamp == -1) {
+        ALOGE("%s: get timestamp for image %p failed! ret: %d",
+                __FUNCTION__, img, ret);
+        return ret;
+    }
 
-    mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = reinterpret_cast<uint8_t*>(bufferPointer);
-    mAlloc[idx]->mHal.drvState.lod[0].stride = mSlots[slot].mGraphicBuffer->getStride() *
-            mAlloc[idx]->mHal.state.type->getElementSizeBytes();
-    mAlloc[idx]->mHal.state.nativeBuffer = mAcquiredBuffer[idx].mGraphicBuffer->getNativeBuffer();
-    mAlloc[idx]->mHal.state.timestamp = b.mTimestamp;
+    int32_t rowstride = -1;
+    ret = AImage_getPlaneRowStride(img, 0, &rowstride);
+    if (ret != AMEDIA_OK || rowstride == -1) {
+        ALOGE("%s: get row stride for image %p failed! ret: %d, rowstride %d",
+                __FUNCTION__, img, ret, rowstride);
+        return ret;
+    }
 
-    rsAssert(mAlloc[idx]->mHal.drvState.lod[0].dimX ==
-             mSlots[slot].mGraphicBuffer->getWidth());
-    rsAssert(mAlloc[idx]->mHal.drvState.lod[0].dimY ==
-             mSlots[slot].mGraphicBuffer->getHeight());
+    mAcquiredBuffer[idx].mBufferPointer = data;
 
-    //mAlloc->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
+    mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = data;
+    mAlloc[idx]->mHal.drvState.lod[0].stride = rowstride;
+    mAlloc[idx]->mHal.state.timestamp = timestamp;
 
-    //mAlloc->crop        = b.mCrop;
-    //mAlloc->transform   = b.mTransform;
-    //mAlloc->scalingMode = b.mScalingMode;
-    //mAlloc->frameNumber = b.mFrameNumber;
-
-    // For YUV Allocations, we need to populate the drvState with details of how
-    // the data is layed out.
-    // RenderScript requests a buffer in the YCbCr_420_888 format.
-    // The Camera HAL can return a buffer of YCbCr_420_888 or YV12, regardless
-    // of the requested format.
-    // mHal.state.yuv contains the requested format,
-    // mGraphicBuffer->getPixelFormat() is the returned format.
-    if (mAlloc[idx]->mHal.state.yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+    if (format == AIMAGE_FORMAT_YUV_420_888) {
         const int yWidth = mAlloc[idx]->mHal.drvState.lod[0].dimX;
         const int yHeight = mAlloc[idx]->mHal.drvState.lod[0].dimY;
 
-        if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
-                HAL_PIXEL_FORMAT_YCbCr_420_888) {
-            const int cWidth = yWidth / 2;
-            const int cHeight = yHeight / 2;
+        const int cWidth = yWidth / 2;
+        const int cHeight = yHeight / 2;
 
-            mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth;
-            mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight;
-            mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth;
-            mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight;
-
-            mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = ycbcr.y;
-            mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = ycbcr.cb;
-            mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = ycbcr.cr;
-
-            mAlloc[idx]->mHal.drvState.lod[0].stride = ycbcr.ystride;
-            mAlloc[idx]->mHal.drvState.lod[1].stride = ycbcr.cstride;
-            mAlloc[idx]->mHal.drvState.lod[2].stride = ycbcr.cstride;
-
-            mAlloc[idx]->mHal.drvState.yuv.shift = 1;
-            mAlloc[idx]->mHal.drvState.yuv.step = ycbcr.chroma_step;
-            mAlloc[idx]->mHal.drvState.lodCount = 3;
-        } else if (mSlots[slot].mGraphicBuffer->getPixelFormat() ==
-                       HAL_PIXEL_FORMAT_YV12) {
-            // For YV12, the data layout is Y, followed by Cr, followed by Cb;
-            // for YCbCr_420_888, it's Y, followed by Cb, followed by Cr.
-            // RenderScript assumes lod[0] is Y, lod[1] is Cb, and lod[2] is Cr.
-            const int cWidth = yWidth / 2;
-            const int cHeight = yHeight / 2;
-
-            mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth;
-            mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight;
-            mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth;
-            mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight;
-
-            size_t yStride = rsRound(yWidth *
-                 mAlloc[idx]->mHal.state.type->getElementSizeBytes(), 16);
-            size_t cStride = rsRound(yStride >> 1, 16);
-
-            uint8_t *yPtr = (uint8_t *)mAlloc[idx]->mHal.drvState.lod[0].mallocPtr;
-            uint8_t *crPtr = yPtr + yStride * yHeight;
-            uint8_t *cbPtr = crPtr + cStride * cHeight;
-
-            mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = cbPtr;
-            mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = crPtr;
-
-            mAlloc[idx]->mHal.drvState.lod[0].stride = yStride;
-            mAlloc[idx]->mHal.drvState.lod[1].stride = cStride;
-            mAlloc[idx]->mHal.drvState.lod[2].stride = cStride;
-
-            mAlloc[idx]->mHal.drvState.yuv.shift = 1;
-            mAlloc[idx]->mHal.drvState.yuv.step = 1;
-            mAlloc[idx]->mHal.drvState.lodCount = 3;
-        } else {
-            ALOGD("Unrecognized format: %d",
-               mSlots[slot].mGraphicBuffer->getPixelFormat());
+        uint8_t *uData = nullptr;
+        int uDataLength = 0;
+        ret =  AImage_getPlaneData(img, 1, &uData, &uDataLength);
+        if (ret != AMEDIA_OK || uData == nullptr || uDataLength <= 0) {
+            ALOGE("%s: get U data for image %p failed! ret: %d, data %p, len %d",
+                    __FUNCTION__, img, ret, uData, uDataLength);
+            return ret;
         }
+
+        uint8_t *vData = nullptr;
+        int vDataLength = 0;
+        ret =  AImage_getPlaneData(img, 2, &vData, &vDataLength);
+        if (ret != AMEDIA_OK || vData == nullptr || vDataLength <= 0) {
+            ALOGE("%s: get V data for image %p failed! ret: %d, data %p, len %d",
+                    __FUNCTION__, img, ret, vData, vDataLength);
+            return ret;
+        }
+
+        int32_t uRowStride = -1;
+        ret = AImage_getPlaneRowStride(img, 1, &uRowStride);
+        if (ret != AMEDIA_OK || uRowStride == -1) {
+            ALOGE("%s: get U row stride for image %p failed! ret: %d, uRowStride %d",
+                    __FUNCTION__, img, ret, uRowStride);
+            return ret;
+        }
+
+        int32_t vRowStride = -1;
+        ret = AImage_getPlaneRowStride(img, 2, &vRowStride);
+        if (ret != AMEDIA_OK || vRowStride == -1) {
+            ALOGE("%s: get V row stride for image %p failed! ret: %d, vRowStride %d",
+                    __FUNCTION__, img, ret, vRowStride);
+            return ret;
+        }
+
+        int32_t uPixStride = -1;
+        ret = AImage_getPlanePixelStride(img, 1, &uPixStride);
+        if (ret != AMEDIA_OK || uPixStride == -1) {
+            ALOGE("%s: get U pixel stride for image %p failed! ret: %d, uPixStride %d",
+                    __FUNCTION__, img, ret, uPixStride);
+            return ret;
+        }
+
+        mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth;
+        mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight;
+        mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth;
+        mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight;
+
+        mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = uData;
+        mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = vData;
+
+        mAlloc[idx]->mHal.drvState.lod[1].stride = uRowStride;
+        mAlloc[idx]->mHal.drvState.lod[2].stride = vRowStride;
+
+        mAlloc[idx]->mHal.drvState.yuv.shift = 1;
+        mAlloc[idx]->mHal.drvState.yuv.step = uPixStride;
+        mAlloc[idx]->mHal.drvState.lodCount = 3;
     }
 
-    return OK;
+    return AMEDIA_OK;
 }
 
-status_t GrallocConsumer::unlockBuffer(uint32_t idx) {
-    Mutex::Autolock _l(mMutex);
-    return releaseAcquiredBufferLocked(idx);
-}
-
-status_t GrallocConsumer::releaseAcquiredBufferLocked(uint32_t idx) {
-    status_t err;
+media_status_t GrallocConsumer::unlockBuffer(uint32_t idx) {
+    media_status_t ret;
 
     if (idx >= mNumAlloc) {
         ALOGE("Invalid buffer index: %d", idx);
-        return BAD_VALUE;
+        return AMEDIA_ERROR_INVALID_PARAMETER;
     }
-    if (mAcquiredBuffer[idx].mGraphicBuffer == nullptr) {
-       return OK;
+    if (mAcquiredBuffer[idx].mImg == nullptr) {
+       return AMEDIA_OK;
     }
 
-    err = mAcquiredBuffer[idx].mGraphicBuffer->unlock();
-    if (err != OK) {
-        ALOGE("%s: Unable to unlock graphic buffer", __FUNCTION__);
-        return err;
-    }
-    int buf = mAcquiredBuffer[idx].mSlot;
-
-    // release the buffer if it hasn't already been freed by the BufferQueue.
-    // This can happen, for example, when the producer of this buffer
-    // disconnected after this buffer was acquired.
-    if (mAcquiredBuffer[idx].mGraphicBuffer == mSlots[buf].mGraphicBuffer) {
-        releaseBufferLocked(
-                buf, mAcquiredBuffer[idx].mGraphicBuffer,
-                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
-    }
-
-    mAcquiredBuffer[idx].mSlot = BufferQueue::INVALID_BUFFER_SLOT;
-    mAcquiredBuffer[idx].mBufferPointer = nullptr;
-    mAcquiredBuffer[idx].mGraphicBuffer.clear();
-    return OK;
+    AImage_delete(mAcquiredBuffer[idx].mImg);
+    mAcquiredBuffer[idx].mImg = nullptr;
+    return AMEDIA_OK;
 }
 
 uint32_t GrallocConsumer::getNextAvailableIdx(Allocation *a) {
@@ -291,9 +255,9 @@
         ALOGV("Buffer index already released: %d", idx);
         return true;
     }
-    status_t err;
-    err = unlockBuffer(idx);
-    if (err != OK) {
+    media_status_t ret;
+    ret = unlockBuffer(idx);
+    if (ret != OK) {
         ALOGE("Unable to unlock graphic buffer");
         return false;
     }
@@ -302,5 +266,14 @@
     return true;
 }
 
+bool GrallocConsumer::isActive() {
+    for (uint32_t i = 0; i < mNumAlloc; i++) {
+        if (isIdxUsed[i]) {
+            return true;
+        }
+    }
+    return false;
+}
+
 } // namespace renderscript
 } // namespace android
diff --git a/rsGrallocConsumer.h b/rsGrallocConsumer.h
index 2c64551..d279145 100644
--- a/rsGrallocConsumer.h
+++ b/rsGrallocConsumer.h
@@ -17,20 +17,15 @@
 #ifndef ANDROID_RS_GRALLOC_CONSUMER_H
 #define ANDROID_RS_GRALLOC_CONSUMER_H
 
-#include <gui/ConsumerBase.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
+#include "NdkImage.h"
+#include "NdkImageReader.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
 namespace renderscript {
 
 class Allocation;
+class Context;
 
 /**
  * CpuConsumer is a BufferQueue consumer endpoint that allows direct CPU
@@ -39,38 +34,39 @@
  * CpuConsumer owner. Sets gralloc usage flags to be software-read-only.
  * This queue is synchronous by default.
  */
-class GrallocConsumer : public ConsumerBase
+class GrallocConsumer
 {
   public:
-    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
-
-    GrallocConsumer(Allocation *, const sp<IGraphicBufferConsumer>& bq, int flags, uint32_t numAlloc);
+    GrallocConsumer(const Context *, Allocation *, uint32_t numAlloc);
 
     virtual ~GrallocConsumer();
-    status_t lockNextBuffer(uint32_t idx = 0);
-    status_t unlockBuffer(uint32_t idx = 0);
+    ANativeWindow* getNativeWindow();
+    media_status_t lockNextBuffer(uint32_t idx = 0);
+    media_status_t unlockBuffer(uint32_t idx = 0);
     uint32_t getNextAvailableIdx(Allocation *a);
     bool releaseIdx(uint32_t idx);
+    bool isActive();
     uint32_t mNumAlloc;
 
+    static void onFrameAvailable(void* obj, AImageReader* reader);
 
   private:
-    status_t releaseAcquiredBufferLocked(uint32_t idx);
+    media_status_t releaseAcquiredBufferLocked(uint32_t idx);
     // Boolean array to check if a position has been occupied or not.
     bool *isIdxUsed;
     Allocation **mAlloc;
 
+    const Context *mCtx;
+    AImageReader* mImgReader;
+    ANativeWindow* mNativeWindow;
+    AImageReader_ImageListener mReaderCb;
     // Tracking for buffers acquired by the user
     struct AcquiredBuffer {
-        // Need to track the original mSlot index and the buffer itself because
-        // the mSlot entry may be freed/reused before the acquired buffer is
-        // released.
-        int mSlot;
-        sp<GraphicBuffer> mGraphicBuffer;
-        void *mBufferPointer;
+        AImage *mImg;
+        uint8_t *mBufferPointer;
 
         AcquiredBuffer() :
-                mSlot(BufferQueue::INVALID_BUFFER_SLOT),
+                mImg(nullptr),
                 mBufferPointer(nullptr) {
         }
     };
diff --git a/rs_hal.h b/rs_hal.h
index 4534126..5d87a50 100644
--- a/rs_hal.h
+++ b/rs_hal.h
@@ -36,7 +36,7 @@
  * !! Be very careful when merging or cherry picking between branches!
  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  */
-#define RS_HAL_VERSION 100
+#define RS_HAL_VERSION 200
 
 /**
  * The interface for loading RenderScript drivers
diff --git a/rsov/driver/Android.mk b/rsov/driver/Android.mk
index 8f4a14f..3183195 100644
--- a/rsov/driver/Android.mk
+++ b/rsov/driver/Android.mk
@@ -43,7 +43,7 @@
     frameworks/compile/libbcc/include \
     frameworks/native/vulkan/include \
     frameworks/rs \
-    frameworks/rs/cpu_ref \
+    frameworks/rs/cpu_ref
 
 LOCAL_C_INCLUDES += \