libui: add support for android.hardware.graphics

Add Gralloc2::Allocator and Gralloc2::Mapper as wrappers to
android.hardware.graphics.allocator@2.0 and
android.hardware.graphics.mapper@2.0 respectively.  Prefer
Gralloc2::{Allocator,Mapper} in
GraphicBufferAllocator/GraphicBufferMapper.

The new path has these differences

 - it does not support gralloc0
 - it does not dup-and-close fence fds to and from HAL
   (not sure why we did that)
 - release implies native_handle_close and native_handle_delete
   (same as in gralloc1?)

When all interesting targets have android.hardware.graphics
implementations, the old path will be removed.  That is why the new path
is added in the least intrusive way, as in:

  if (new-path-valid) {
    new-path;
  } else {
    old-path;
  }

despite the ugliness.

Test: booted to launcher, tested with YouTube and some games
Change-Id: Idabb6c62e73c96a59736b497c6d6d1366095e7e3
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 0777468..1dc40b3 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -46,6 +46,8 @@
         "FrameStats.cpp",
         "Gralloc1.cpp",
         "Gralloc1On0Adapter.cpp",
+        "GrallocAllocator.cpp",
+        "GrallocMapper.cpp",
         "GraphicBuffer.cpp",
         "GraphicBufferAllocator.cpp",
         "GraphicBufferMapper.cpp",
@@ -56,10 +58,17 @@
         "UiConfig.cpp",
     ],
 
+    static_libs: [
+        "android.hardware.graphics.mapper@2.0",
+    ],
+
     shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
         "libbinder",
         "libcutils",
         "libhardware",
+        "libhidl",
+        "libhwbinder",
         "libsync",
         "libutils",
         "liblog",
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
new file mode 100644
index 0000000..2eb1988
--- /dev/null
+++ b/libs/ui/GrallocAllocator.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GrallocAllocator"
+
+#include <log/log.h>
+#include <ui/GrallocAllocator.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+// assume NO_RESOURCES when Status::isOk returns false
+constexpr Error kDefaultError = Error::NO_RESOURCES;
+
+Allocator::Allocator()
+{
+    mService = IAllocator::getService("gralloc");
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+    std::string info;
+
+    mService->dumpDebugInfo([&](const auto& tmpInfo) {
+        info = tmpInfo.c_str();
+    });
+
+    return info;
+}
+
+Error Allocator::createBufferDescriptor(
+        const IAllocator::BufferDescriptorInfo& descriptorInfo,
+        BufferDescriptor& descriptor) const
+{
+    Error error = kDefaultError;
+    mService->createDescriptor(descriptorInfo,
+            [&](const auto& tmpError, const auto& tmpDescriptor) {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                descriptor = tmpDescriptor;
+            });
+
+    return error;
+}
+
+void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
+{
+    mService->destroyDescriptor(descriptor);
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, Buffer& buffer) const
+{
+    hardware::hidl_vec<BufferDescriptor> descriptors;
+    descriptors.setToExternal(&descriptor, 1);
+
+    Error error = kDefaultError;
+    auto status = mService->allocate(descriptors,
+            [&](const auto& tmpError, const auto& tmpBuffers) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                buffer = tmpBuffers[0];
+            });
+
+    return error;
+}
+
+void Allocator::free(Buffer buffer) const
+{
+    mService->free(buffer);
+}
+
+Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
+        native_handle_t*& bufferHandle) const
+{
+    Error error = kDefaultError;
+    auto status = mService->exportHandle(descriptor, buffer,
+            [&](const auto& tmpError, const auto& tmpBufferHandle) {
+                error = tmpError;
+                if (tmpError != Error::NONE) {
+                    return;
+                }
+
+                bufferHandle = native_handle_clone(tmpBufferHandle);
+                if (!bufferHandle) {
+                    error = Error::NO_RESOURCES;
+                }
+            });
+
+    return error;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
new file mode 100644
index 0000000..d568b68
--- /dev/null
+++ b/libs/ui/GrallocMapper.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GrallocMapper"
+
+#include <array>
+#include <string>
+
+#include <log/log.h>
+#include <ui/GrallocMapper.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+typedef const void*(*FetchInterface)(const char* name);
+
+static FetchInterface loadHalLib(const char* pkg_name)
+{
+    static const std::array<const char*, 3> sSearchDirs = {{
+        HAL_LIBRARY_PATH_ODM,
+        HAL_LIBRARY_PATH_VENDOR,
+        HAL_LIBRARY_PATH_SYSTEM,
+    }};
+    static const char sSymbolName[] = "HALLIB_FETCH_Interface";
+
+    void* handle = nullptr;
+    std::string path;
+    for (auto dir : sSearchDirs) {
+        path = dir;
+        path += pkg_name;
+        path += ".hallib.so";
+        handle = dlopen(path.c_str(), RTLD_LOCAL | RTLD_NOW);
+        if (handle) {
+            break;
+        }
+    }
+    if (!handle) {
+        return nullptr;
+    }
+
+    void* symbol = dlsym(handle, sSymbolName);
+    if (!symbol) {
+        ALOGE("%s is missing from %s", sSymbolName, path.c_str());
+        dlclose(handle);
+        return nullptr;
+    }
+
+    return reinterpret_cast<FetchInterface>(symbol);
+}
+
+Mapper::Mapper()
+    : mMapper(nullptr), mDevice(nullptr)
+{
+    static const char sHalLibName[] = "android.hardware.graphics.mapper";
+    static const char sSupportedInterface[] =
+        "android.hardware.graphics.mapper@2.0::IMapper";
+
+    FetchInterface fetchInterface = loadHalLib(sHalLibName);
+    if (!fetchInterface) {
+        return;
+    }
+
+    mMapper = static_cast<const IMapper*>(
+            fetchInterface(sSupportedInterface));
+    if (!mMapper) {
+        ALOGE("%s is not supported", sSupportedInterface);
+        return;
+    }
+
+    if (mMapper->createDevice(&mDevice) != Error::NONE) {
+        ALOGE("failed to create mapper device");
+        mMapper = nullptr;
+    }
+}
+
+Mapper::~Mapper()
+{
+    if (mMapper) {
+        mMapper->destroyDevice(mDevice);
+    }
+}
+
+void Mapper::release(buffer_handle_t handle) const
+{
+    auto error = mMapper->release(mDevice, handle);
+    ALOGE_IF(error != Error::NONE,
+            "release(%p) failed with %d", handle, error);
+}
+
+int Mapper::unlock(buffer_handle_t handle) const
+{
+    int releaseFence;
+    auto error = mMapper->unlock(mDevice, handle, &releaseFence);
+    if (error != Error::NONE) {
+        ALOGE("unlock(%p) failed with %d", handle, error);
+        releaseFence = -1;
+    }
+
+    return releaseFence;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 97b948d..6d72900 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -23,6 +23,7 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include <ui/GrallocMapper.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/GraphicBufferMapper.h>
@@ -108,8 +109,10 @@
 {
     if (mOwner == ownHandle) {
         mBufferMapper.unregisterBuffer(handle);
-        native_handle_close(handle);
-        native_handle_delete(const_cast<native_handle*>(handle));
+        if (!mBufferMapper.getGrallocMapper().valid()) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle*>(handle));
+        }
     } else if (mOwner == ownData) {
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index edfff4d..693c7cb 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -26,6 +26,9 @@
 
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/Gralloc1On0Adapter.h>
+#include <ui/GrallocAllocator.h>
+#include <ui/GrallocMapper.h>
+#include <ui/GraphicBufferMapper.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -37,8 +40,14 @@
     GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
 
 GraphicBufferAllocator::GraphicBufferAllocator()
-  : mLoader(std::make_unique<Gralloc1::Loader>()),
-    mDevice(mLoader->getDevice()) {}
+  : mAllocator(std::make_unique<Gralloc2::Allocator>()),
+    mMapper(GraphicBufferMapper::getInstance())
+{
+    if (!mAllocator->valid()) {
+        mLoader = std::make_unique<Gralloc1::Loader>();
+        mDevice = mLoader->getDevice();
+    }
+}
 
 GraphicBufferAllocator::~GraphicBufferAllocator() {}
 
@@ -70,7 +79,14 @@
     }
     snprintf(buffer, SIZE, "Total allocated (estimate): %.2f KB\n", total/1024.0f);
     result.append(buffer);
-    std::string deviceDump = mDevice->dump();
+
+    std::string deviceDump;
+    if (mAllocator->valid()) {
+        deviceDump = mAllocator->dumpDebugInfo();
+    } else {
+        deviceDump = mDevice->dump();
+    }
+
     result.append(deviceDump.c_str(), deviceDump.size());
 }
 
@@ -81,6 +97,103 @@
     ALOGD("%s", s.string());
 }
 
+namespace {
+
+class HalBuffer {
+public:
+    HalBuffer(const Gralloc2::Allocator* allocator,
+            uint32_t width, uint32_t height,
+            PixelFormat format, uint32_t usage)
+        : mAllocator(allocator), mBufferValid(false)
+    {
+        Gralloc2::IAllocator::BufferDescriptorInfo info = {};
+        info.width = width;
+        info.height = height;
+        info.format = static_cast<Gralloc2::PixelFormat>(format);
+        info.producerUsageMask = usage;
+        info.consumerUsageMask = usage;
+
+        Gralloc2::BufferDescriptor descriptor;
+        auto error = mAllocator->createBufferDescriptor(info, descriptor);
+        if (error != Gralloc2::Error::NONE) {
+            ALOGE("Failed to create desc (%u x %u) format %d usage %u: %d",
+                    width, height, format, usage, error);
+            return;
+        }
+
+        error = mAllocator->allocate(descriptor, mBuffer);
+        if (error == Gralloc2::Error::NOT_SHARED) {
+            error = Gralloc2::Error::NONE;
+        }
+
+        if (error != Gralloc2::Error::NONE) {
+            ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",
+                    width, height, format, usage, error);
+            mAllocator->destroyBufferDescriptor(descriptor);
+            return;
+        }
+
+        error = mAllocator->exportHandle(descriptor, mBuffer, mHandle);
+        if (error != Gralloc2::Error::NONE) {
+            ALOGE("Failed to export handle");
+            mAllocator->free(mBuffer);
+            mAllocator->destroyBufferDescriptor(descriptor);
+            return;
+        }
+
+        mAllocator->destroyBufferDescriptor(descriptor);
+
+        mBufferValid = true;
+    }
+
+    ~HalBuffer()
+    {
+        if (mBufferValid) {
+            if (mHandle) {
+                native_handle_close(mHandle);
+                native_handle_delete(mHandle);
+            }
+
+            mAllocator->free(mBuffer);
+        }
+    }
+
+    bool exportHandle(GraphicBufferMapper& mapper,
+            buffer_handle_t* handle, uint32_t* stride)
+    {
+        if (!mBufferValid) {
+            return false;
+        }
+
+        if (mapper.registerBuffer(mHandle)) {
+            return false;
+        }
+
+        *handle = mHandle;
+
+        auto error = mapper.getGrallocMapper().getStride(mHandle, *stride);
+        if (error != Gralloc2::Error::NONE) {
+            ALOGW("Failed to get stride from buffer: %d", error);
+            *stride = 0;
+        }
+
+        mHandle = nullptr;
+        mAllocator->free(mBuffer);
+        mBufferValid = false;
+
+        return true;
+    }
+
+private:
+    const Gralloc2::Allocator* mAllocator;
+
+    bool mBufferValid;
+    Gralloc2::Buffer mBuffer;
+    native_handle_t* mHandle;
+};
+
+} // namespace
+
 status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
         PixelFormat format, uint32_t usage, buffer_handle_t* handle,
         uint32_t* stride, uint64_t graphicBufferId, std::string requestorName)
@@ -95,40 +208,51 @@
     // Filter out any usage bits that should not be passed to the gralloc module
     usage &= GRALLOC_USAGE_ALLOC_MASK;
 
-    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;
-    }
+    gralloc1_error_t error;
+    if (mAllocator->valid()) {
+        HalBuffer buffer(mAllocator.get(), width, height, format, usage);
+        if (!buffer.exportHandle(mMapper, handle, stride)) {
+            return NO_MEMORY;
+        }
+        error = GRALLOC1_ERROR_NONE;
+    } else {
+        auto descriptor = mDevice->createDescriptor();
+        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;
+        }
 
-    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;
-    }
+        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;
+        }
 
-    error = mDevice->getStride(*handle, stride);
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGW("Failed to get stride from buffer: %d", error);
+        error = mDevice->getStride(*handle, stride);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGW("Failed to get stride from buffer: %d", error);
+        }
     }
 
     if (error == NO_ERROR) {
@@ -153,7 +277,14 @@
 {
     ATRACE_CALL();
 
-    auto error = mDevice->release(handle);
+    gralloc1_error_t error;
+    if (mAllocator->valid()) {
+        error = static_cast<gralloc1_error_t>(
+                mMapper.unregisterBuffer(handle));
+    } else {
+        error = mDevice->release(handle);
+    }
+
     if (error != GRALLOC1_ERROR_NONE) {
         ALOGE("Failed to free buffer: %d", error);
     }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 481d43c..fb55bf1 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -33,6 +33,7 @@
 #include <utils/Trace.h>
 
 #include <ui/Gralloc1On0Adapter.h>
+#include <ui/GrallocMapper.h>
 #include <ui/GraphicBufferMapper.h>
 #include <ui/Rect.h>
 
@@ -44,8 +45,13 @@
 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )
 
 GraphicBufferMapper::GraphicBufferMapper()
-  : mLoader(std::make_unique<Gralloc1::Loader>()),
-    mDevice(mLoader->getDevice()) {}
+  : mMapper(std::make_unique<const Gralloc2::Mapper>())
+{
+    if (!mMapper->valid()) {
+        mLoader = std::make_unique<Gralloc1::Loader>();
+        mDevice = mLoader->getDevice();
+    }
+}
 
 
 
@@ -53,7 +59,13 @@
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error = mDevice->retain(handle);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
+    } else {
+        error = mDevice->retain(handle);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
             handle, error);
 
@@ -64,7 +76,14 @@
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error = mDevice->retain(buffer);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        error = static_cast<gralloc1_error_t>(
+                mMapper->retain(buffer->getNativeBuffer()->handle));
+    } else {
+        error = mDevice->retain(buffer);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
             buffer->getNativeBuffer()->handle, error);
 
@@ -75,7 +94,14 @@
 {
     ATRACE_CALL();
 
-    gralloc1_error_t error = mDevice->release(handle);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        mMapper->release(handle);
+        error = GRALLOC1_ERROR_NONE;
+    } else {
+        error = mDevice->release(handle);
+    }
+
     ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
             handle, error);
 
@@ -120,11 +146,20 @@
     ATRACE_CALL();
 
     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);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        const Gralloc2::Device::Rect& accessRect =
+            *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
+        error = static_cast<gralloc1_error_t>(mMapper->lock(
+                    handle, usage, usage, accessRect, fenceFd, *vaddr));
+    } else {
+        sp<Fence> fence = new Fence(fenceFd);
+        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);
 
@@ -160,20 +195,29 @@
     ATRACE_CALL();
 
     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;
+    if (!mMapper->valid()) {
+        if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
+            sp<Fence> fence = new Fence(fenceFd);
+            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;
+        }
     }
 
     uint32_t numPlanes = 0;
-    gralloc1_error_t error = mDevice->getNumFlexPlanes(handle, &numPlanes);
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        error = static_cast<gralloc1_error_t>(
+                mMapper->getNumFlexPlanes(handle, numPlanes));
+    } else {
+        error = mDevice->getNumFlexPlanes(handle, &numPlanes);
+    }
+
     if (error != GRALLOC1_ERROR_NONE) {
         ALOGV("Failed to retrieve number of flex planes: %d", error);
         return error;
@@ -188,10 +232,21 @@
     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 (mMapper->valid()) {
+        const Gralloc2::Device::Rect& accessRect =
+            *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
+        Gralloc2::FlexLayout& layout =
+            *reinterpret_cast<Gralloc2::FlexLayout*>(&flexLayout);
+        error = static_cast<gralloc1_error_t>(mMapper->lock(
+                    handle, usage, usage, accessRect, fenceFd, layout));
+    } else {
+        sp<Fence> fence = new Fence(fenceFd);
+        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;
@@ -276,14 +331,20 @@
 {
     ATRACE_CALL();
 
-    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;
-    }
+    gralloc1_error_t error;
+    if (mMapper->valid()) {
+        *fenceFd = mMapper->unlock(handle);
+        error = GRALLOC1_ERROR_NONE;
+    } else {
+        sp<Fence> fence = Fence::NO_FENCE;
+        error = mDevice->unlock(handle, &fence);
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGE("unlock(%p) failed: %d", handle, error);
+            return error;
+        }
 
-    *fenceFd = fence->dup();
+        *fenceFd = fence->dup();
+    }
     return error;
 }