Squashed: gralloc1/binder/requestor

This is a combination of the following three commits:

libui: Convert Allocator and Mapper to gralloc1

Converts GraphicBufferAllocator and GraphicBufferMapper to speak
gralloc 1.0 (via the C++ shim and optionally the 1On0 adapter) instead
of gralloc 0.x.

-----

Create graphic buffer using binder interfaces

Using binder interfaces rather than directly allocating the buffer prevents
SELinux warnings.

-----

Add requestor name to GraphicBuffer alloc metadata

Adds a requestor name (usually the BufferQueue consumer's name) to the
metadata that GraphicBufferAllocator stores on allocation so that
`dumpsys SurfaceFlinger` can attempt to attribute buffer usage to the
correct client.

Bug: 28401203
Bug: 29402015
Bug: 30776557
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index be3b6c3..88df6d2 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -496,7 +496,8 @@
         status_t error;
         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
         sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
-                width, height, format, usage, &error));
+                width, height, format, usage,
+                {mConsumerName.string(), mConsumerName.size()}, &error));
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
 
@@ -1255,7 +1256,8 @@
         for (size_t i = 0; i <  newBufferCount; ++i) {
             status_t result = NO_ERROR;
             sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
-                    allocWidth, allocHeight, allocFormat, allocUsage, &result));
+                    allocWidth, allocHeight, allocFormat, allocUsage,
+                    {mConsumerName.string(), mConsumerName.size()}, &result));
             if (result != NO_ERROR) {
                 BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
                         " %u, usage %u)", width, height, format, usage);
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 553b65c..aa0db45 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -345,7 +345,8 @@
         // continues to use it.
         sp<GraphicBuffer> buffer = new GraphicBuffer(
                 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
-                GraphicBuffer::USAGE_SW_WRITE_RARELY);
+                GraphicBuffer::USAGE_SW_WRITE_RARELY,
+                "[GLConsumer debug texture]");
         uint32_t* bits;
         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
         uint32_t stride = buffer->getStride();
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
index 9643402..e6150f4 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -32,9 +32,10 @@
 }
 
 sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t usage, status_t* error) {
-    sp<GraphicBuffer> graphicBuffer(
-            new GraphicBuffer(width, height, format, usage));
+        uint32_t height, PixelFormat format, uint32_t usage,
+        std::string requestorName, status_t* error) {
+    sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
+            width, height, format, usage, std::move(requestorName)));
     status_t err = graphicBuffer->initCheck();
     *error = err;
     if (err != 0 || graphicBuffer->handle == 0) {
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index d4d4702..2fb380c 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -46,13 +46,19 @@
 
     virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
             uint32_t height, PixelFormat format, uint32_t usage,
-            status_t* error) {
+            std::string requestorName, status_t* error) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
         data.writeUint32(usage);
+        if (requestorName.empty()) {
+            requestorName += "[PID ";
+            requestorName += std::to_string(getpid());
+            requestorName += ']';
+        }
+        data.writeUtf8AsUtf16(requestorName);
         remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
         sp<GraphicBuffer> graphicBuffer;
         status_t result = reply.readInt32();
@@ -101,9 +107,11 @@
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            status_t error;
-            sp<GraphicBuffer> result =
-                    createGraphicBuffer(width, height, format, usage, &error);
+            status_t error = NO_ERROR;
+            std::string requestorName;
+            data.readUtf8FromUtf16(&requestorName);
+            sp<GraphicBuffer> result = createGraphicBuffer(width, height,
+                    format, usage, requestorName, &error);
             reply->writeInt32(error);
             if (result != 0) {
                 reply->write(*result);
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 4fe0946..97b948d 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -54,7 +54,7 @@
 }
 
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inUsage)
+        PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
       mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
 {
@@ -64,7 +64,8 @@
     format =
     usage  = 0;
     handle = NULL;
-    mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage);
+    mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage,
+            std::move(requestorName));
 }
 
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
@@ -151,7 +152,7 @@
         allocator.free(handle);
         handle = 0;
     }
-    return initSize(inWidth, inHeight, inFormat, inUsage);
+    return initSize(inWidth, inHeight, inFormat, inUsage, "[Reallocation]");
 }
 
 bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
@@ -165,12 +166,12 @@
 }
 
 status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
-        PixelFormat inFormat, uint32_t inUsage)
+        PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
 {
     GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
     uint32_t outStride = 0;
-    status_t err = allocator.alloc(inWidth, inHeight, inFormat, inUsage,
-            &handle, &outStride);
+    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inUsage,
+            &handle, &outStride, mId, std::move(requestorName));
     if (err == NO_ERROR) {
         width = static_cast<int>(inWidth);
         height = static_cast<int>(inHeight);
@@ -390,7 +391,7 @@
     mOwner = ownHandle;
 
     if (handle != 0) {
-        status_t err = mBufferMapper.registerBuffer(handle);
+        status_t err = mBufferMapper.registerBuffer(this);
         if (err != NO_ERROR) {
             width = height = stride = format = usage = 0;
             handle = NULL;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 9b265af..edfff4d 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -25,6 +25,7 @@
 #include <utils/Trace.h>
 
 #include <ui/GraphicBufferAllocator.h>
+#include <ui/Gralloc1On0Adapter.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -36,20 +37,10 @@
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
 GraphicBufferAllocator::GraphicBufferAllocator()
-    : mAllocDev(0)
-{
-    hw_module_t const* module;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
-    if (err == 0) {
-        gralloc_open(module, &mAllocDev);
-    }
-}
+  : mLoader(std::make_unique<Gralloc1::Loader>()),
+    mDevice(mLoader->getDevice()) {}
 
-GraphicBufferAllocator::~GraphicBufferAllocator()
-{
-    gralloc_close(mAllocDev);
-}
+GraphicBufferAllocator::~GraphicBufferAllocator() {}
 
 void GraphicBufferAllocator::dump(String8& result) const
 {
@@ -64,23 +55,23 @@
     for (size_t i=0 ; i<c ; i++) {
         const alloc_rec_t& rec(list.valueAt(i));
         if (rec.size) {
-            snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x\n",
+            snprintf(buffer, SIZE, "%10p: %7.2f KiB | %4u (%4u) x %4u | %8X | 0x%08x | %s\n",
                     list.keyAt(i), rec.size/1024.0f,
-                    rec.width, rec.stride, rec.height, rec.format, rec.usage);
+                    rec.width, rec.stride, rec.height, rec.format, rec.usage,
+                    rec.requestorName.c_str());
         } else {
-            snprintf(buffer, SIZE, "%10p: unknown     | %4u (%4u) x %4u | %8X | 0x%08x\n",
+            snprintf(buffer, SIZE, "%10p: unknown     | %4u (%4u) x %4u | %8X | 0x%08x | %s\n",
                     list.keyAt(i),
-                    rec.width, rec.stride, rec.height, rec.format, rec.usage);
+                    rec.width, rec.stride, rec.height, rec.format, rec.usage,
+                    rec.requestorName.c_str());
         }
         result.append(buffer);
         total += rec.size;
     }
     snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0f);
     result.append(buffer);
-    if (mAllocDev->common.version >= 1 && mAllocDev->dump) {
-        mAllocDev->dump(mAllocDev, buffer, SIZE);
-        result.append(buffer);
-    }
+    std::string deviceDump = mDevice->dump();
+    result.append(deviceDump.c_str(), deviceDump.size());
 }
 
 void GraphicBufferAllocator::dumpToSystemLog()
@@ -90,9 +81,9 @@
     ALOGD("%s", s.string());
 }
 
-status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,
+status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
         PixelFormat format, uint32_t usage, buffer_handle_t* handle,
-        uint32_t* stride)
+        uint32_t* stride, uint64_t graphicBufferId, std::string requestorName)
 {
     ATRACE_CALL();
 
@@ -101,22 +92,46 @@
     if (!width || !height)
         width = height = 1;
 
-    // we have a h/w allocator and h/w buffer is requested
-    status_t err;
-
     // Filter out any usage bits that should not be passed to the gralloc module
     usage &= GRALLOC_USAGE_ALLOC_MASK;
 
-    int outStride = 0;
-    err = mAllocDev->alloc(mAllocDev, static_cast<int>(width),
-            static_cast<int>(height), format, static_cast<int>(usage), handle,
-            &outStride);
-    *stride = static_cast<uint32_t>(outStride);
+    auto descriptor = mDevice->createDescriptor();
+    auto error = descriptor->setDimensions(width, height);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("Failed to set dimensions to (%u, %u): %d", width, height, error);
+        return BAD_VALUE;
+    }
+    error = descriptor->setFormat(static_cast<android_pixel_format_t>(format));
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("Failed to set format to %d: %d", format, error);
+        return BAD_VALUE;
+    }
+    error = descriptor->setProducerUsage(
+            static_cast<gralloc1_producer_usage_t>(usage));
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("Failed to set producer usage to %u: %d", usage, error);
+        return BAD_VALUE;
+    }
+    error = descriptor->setConsumerUsage(
+            static_cast<gralloc1_consumer_usage_t>(usage));
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("Failed to set consumer usage to %u: %d", usage, error);
+        return BAD_VALUE;
+    }
 
-    ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
-            width, height, format, usage, err, strerror(-err));
+    error = mDevice->allocate(descriptor, graphicBufferId, handle);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
+                width, height, format, usage, error);
+        return NO_MEMORY;
+    }
 
-    if (err == NO_ERROR) {
+    error = mDevice->getStride(*handle, stride);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGW("Failed to get stride from buffer: %d", error);
+    }
+
+    if (error == NO_ERROR) {
         Mutex::Autolock _l(sLock);
         KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
         uint32_t bpp = bytesPerPixel(format);
@@ -127,27 +142,27 @@
         rec.format = format;
         rec.usage = usage;
         rec.size = static_cast<size_t>(height * (*stride) * bpp);
+        rec.requestorName = std::move(requestorName);
         list.add(*handle, rec);
     }
 
-    return err;
+    return NO_ERROR;
 }
 
 status_t GraphicBufferAllocator::free(buffer_handle_t handle)
 {
     ATRACE_CALL();
-    status_t err;
 
-    err = mAllocDev->free(mAllocDev, handle);
-
-    ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
-    if (err == NO_ERROR) {
-        Mutex::Autolock _l(sLock);
-        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
-        list.removeItem(handle);
+    auto error = mDevice->release(handle);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("Failed to free buffer: %d", error);
     }
 
-    return err;
+    Mutex::Autolock _l(sLock);
+    KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
+    list.removeItem(handle);
+
+    return NO_ERROR;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 90a1c11..481d43c 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "GraphicBufferMapper"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
 
 #include <stdint.h>
 #include <errno.h>
@@ -31,11 +32,11 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
+#include <ui/Gralloc1On0Adapter.h>
 #include <ui/GraphicBufferMapper.h>
 #include <ui/Rect.h>
 
-#include <hardware/gralloc.h>
-
+#include <system/graphics.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -43,151 +44,247 @@
 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
 
 GraphicBufferMapper::GraphicBufferMapper()
-    : mAllocMod(0)
-{
-    hw_module_t const* module;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
-    if (err == 0) {
-        mAllocMod = reinterpret_cast<gralloc_module_t const *>(module);
-    }
-}
+  : mLoader(std::make_unique<Gralloc1::Loader>()),
+    mDevice(mLoader->getDevice()) {}
+
+
 
 status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
 {
     ATRACE_CALL();
-    status_t err;
 
-    err = mAllocMod->registerBuffer(mAllocMod, handle);
+    gralloc1_error_t error = mDevice->retain(handle);
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
+            handle, error);
 
-    ALOGW_IF(err, "registerBuffer(%p) failed %d (%s)",
-            handle, err, strerror(-err));
-    return err;
+    return error;
+}
+
+status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
+{
+    ATRACE_CALL();
+
+    gralloc1_error_t error = mDevice->retain(buffer);
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
+            buffer->getNativeBuffer()->handle, error);
+
+    return error;
 }
 
 status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
 {
     ATRACE_CALL();
-    status_t err;
 
-    err = mAllocMod->unregisterBuffer(mAllocMod, handle);
+    gralloc1_error_t error = mDevice->release(handle);
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
+            handle, error);
 
-    ALOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)",
-            handle, err, strerror(-err));
-    return err;
+    return error;
 }
 
-status_t GraphicBufferMapper::lock(buffer_handle_t handle,
-        uint32_t usage, const Rect& bounds, void** vaddr)
-{
-    ATRACE_CALL();
-    status_t err;
-
-    err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage),
-            bounds.left, bounds.top, bounds.width(), bounds.height(),
-            vaddr);
-
-    ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
-    return err;
+static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {
+    gralloc1_rect_t outRect{};
+    outRect.left = rect.left;
+    outRect.top = rect.top;
+    outRect.width = rect.width();
+    outRect.height = rect.height();
+    return outRect;
 }
 
-status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle,
-        uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr)
+status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
+        const Rect& bounds, void** vaddr)
 {
-    ATRACE_CALL();
-    status_t err;
+    return lockAsync(handle, usage, bounds, vaddr, -1);
+}
 
-    if (mAllocMod->lock_ycbcr == NULL) {
-        return -EINVAL; // do not log failure
-    }
-
-    err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage),
-            bounds.left, bounds.top, bounds.width(), bounds.height(),
-            ycbcr);
-
-    ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
-    return err;
+status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,
+        const Rect& bounds, android_ycbcr *ycbcr)
+{
+    return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
 }
 
 status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
 {
-    ATRACE_CALL();
-    status_t err;
-
-    err = mAllocMod->unlock(mAllocMod, handle);
-
-    ALOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
-    return err;
+    int32_t fenceFd = -1;
+    status_t error = unlockAsync(handle, &fenceFd);
+    if (error == NO_ERROR) {
+        sync_wait(fenceFd, -1);
+        close(fenceFd);
+    }
+    return error;
 }
 
 status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,
         uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
 {
     ATRACE_CALL();
-    status_t err;
 
-    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
-        err = mAllocMod->lockAsync(mAllocMod, handle, static_cast<int>(usage),
-                bounds.left, bounds.top, bounds.width(), bounds.height(),
-                vaddr, fenceFd);
-    } else {
-        if (fenceFd >= 0) {
-            sync_wait(fenceFd, -1);
-            close(fenceFd);
-        }
-        err = mAllocMod->lock(mAllocMod, handle, static_cast<int>(usage),
-                bounds.left, bounds.top, bounds.width(), bounds.height(),
-                vaddr);
+    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
+    sp<Fence> fence = new Fence(fenceFd);
+    gralloc1_error_t error = mDevice->lock(handle,
+            static_cast<gralloc1_producer_usage_t>(usage),
+            static_cast<gralloc1_consumer_usage_t>(usage),
+            &accessRegion, vaddr, fence);
+    ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,
+            error);
+
+    return error;
+}
+
+static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {
+    if (plane.bits_per_component != 8) {
+        ALOGV("Invalid number of bits per component: %d",
+                plane.bits_per_component);
+        return false;
+    }
+    if (plane.bits_used != 8) {
+        ALOGV("Invalid number of bits used: %d", plane.bits_used);
+        return false;
     }
 
-    ALOGW_IF(err, "lockAsync(...) failed %d (%s)", err, strerror(-err));
-    return err;
+    bool hasValidIncrement = plane.h_increment == 1 ||
+            (plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2);
+    hasValidIncrement = hasValidIncrement && plane.v_increment > 0;
+    if (!hasValidIncrement) {
+        ALOGV("Invalid increment: h %d v %d", plane.h_increment,
+                plane.v_increment);
+        return false;
+    }
+
+    return true;
 }
 
 status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,
         uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
 {
     ATRACE_CALL();
-    status_t err;
 
-    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3
-            && mAllocMod->lockAsync_ycbcr != NULL) {
-        err = mAllocMod->lockAsync_ycbcr(mAllocMod, handle,
-                static_cast<int>(usage), bounds.left, bounds.top,
-                bounds.width(), bounds.height(), ycbcr, fenceFd);
-    } else if (mAllocMod->lock_ycbcr != NULL) {
-        if (fenceFd >= 0) {
-            sync_wait(fenceFd, -1);
-            close(fenceFd);
-        }
-        err = mAllocMod->lock_ycbcr(mAllocMod, handle, static_cast<int>(usage),
-                bounds.left, bounds.top, bounds.width(), bounds.height(),
-                ycbcr);
-    } else {
-        if (fenceFd >= 0) {
-            close(fenceFd);
-        }
-        return -EINVAL; // do not log failure
+    gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
+    sp<Fence> fence = new Fence(fenceFd);
+
+    if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
+        gralloc1_error_t error = mDevice->lockYCbCr(handle,
+                static_cast<gralloc1_producer_usage_t>(usage),
+                static_cast<gralloc1_consumer_usage_t>(usage),
+                &accessRegion, ycbcr, fence);
+        ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lockYCbCr(%p, ...) failed: %d",
+                handle, error);
+        return error;
     }
 
-    ALOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
-    return err;
+    uint32_t numPlanes = 0;
+    gralloc1_error_t error = mDevice->getNumFlexPlanes(handle, &numPlanes);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGV("Failed to retrieve number of flex planes: %d", error);
+        return error;
+    }
+    if (numPlanes < 3) {
+        ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+
+    std::vector<android_flex_plane_t> planes(numPlanes);
+    android_flex_layout_t flexLayout{};
+    flexLayout.num_planes = numPlanes;
+    flexLayout.planes = planes.data();
+
+    error = mDevice->lockFlex(handle,
+            static_cast<gralloc1_producer_usage_t>(usage),
+            static_cast<gralloc1_consumer_usage_t>(usage),
+            &accessRegion, &flexLayout, fence);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGW("lockFlex(%p, ...) failed: %d", handle, error);
+        return error;
+    }
+    if (flexLayout.format != FLEX_FORMAT_YCbCr) {
+        ALOGV("Unable to convert flex-format buffer to YCbCr");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+
+    // Find planes
+    auto yPlane = planes.cend();
+    auto cbPlane = planes.cend();
+    auto crPlane = planes.cend();
+    for (auto planeIter = planes.cbegin(); planeIter != planes.cend();
+            ++planeIter) {
+        if (planeIter->component == FLEX_COMPONENT_Y) {
+            yPlane = planeIter;
+        } else if (planeIter->component == FLEX_COMPONENT_Cb) {
+            cbPlane = planeIter;
+        } else if (planeIter->component == FLEX_COMPONENT_Cr) {
+            crPlane = planeIter;
+        }
+    }
+    if (yPlane == planes.cend()) {
+        ALOGV("Unable to find Y plane");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+    if (cbPlane == planes.cend()) {
+        ALOGV("Unable to find Cb plane");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+    if (crPlane == planes.cend()) {
+        ALOGV("Unable to find Cr plane");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+
+    // Validate planes
+    if (!isValidYCbCrPlane(*yPlane)) {
+        ALOGV("Y plane is invalid");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+    if (!isValidYCbCrPlane(*cbPlane)) {
+        ALOGV("Cb plane is invalid");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+    if (!isValidYCbCrPlane(*crPlane)) {
+        ALOGV("Cr plane is invalid");
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+    if (cbPlane->v_increment != crPlane->v_increment) {
+        ALOGV("Cb and Cr planes have different step (%d vs. %d)",
+                cbPlane->v_increment, crPlane->v_increment);
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+    if (cbPlane->h_increment != crPlane->h_increment) {
+        ALOGV("Cb and Cr planes have different stride (%d vs. %d)",
+                cbPlane->h_increment, crPlane->h_increment);
+        unlock(handle);
+        return GRALLOC1_ERROR_UNSUPPORTED;
+    }
+
+    // Pack plane data into android_ycbcr struct
+    ycbcr->y = yPlane->top_left;
+    ycbcr->cb = cbPlane->top_left;
+    ycbcr->cr = crPlane->top_left;
+    ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);
+    ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);
+    ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);
+
+    return error;
 }
 
 status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
 {
     ATRACE_CALL();
-    status_t err;
 
-    if (mAllocMod->common.module_api_version >= GRALLOC_MODULE_API_VERSION_0_3) {
-        err = mAllocMod->unlockAsync(mAllocMod, handle, fenceFd);
-    } else {
-        *fenceFd = -1;
-        err = mAllocMod->unlock(mAllocMod, handle);
+    sp<Fence> fence = Fence::NO_FENCE;
+    gralloc1_error_t error = mDevice->unlock(handle, &fence);
+    if (error != GRALLOC1_ERROR_NONE) {
+        ALOGE("unlock(%p) failed: %d", handle, error);
+        return error;
     }
 
-    ALOGW_IF(err, "unlockAsync(...) failed %d (%s)", err, strerror(-err));
-    return err;
+    *fenceFd = fence->dup();
+    return error;
 }
 
 // ---------------------------------------------------------------------------