graphics: make mapper default impl a header library

Reimplement the default impl as a header-only library,
android.hardware.graphics.mapper@2.0-passthrough, based on the HAL
support library.

Effectively, this renames Gralloc[01]Mapper to Gralloc[01]Hal, and
make adjustments here and there to meet the requirements of the HAL
support library.  This also adds GrallocLoader to load either of
Gralloc[01]Hal and create an IMapper instance.

libgrallocmapperincludes is renamed to follow the new naming and
include path conventions.

Test: boots and VTS
Change-Id: I924cadce9a10a6e544f99ceba63aadc38ec431ac
diff --git a/graphics/mapper/2.0/utils/passthrough/Android.bp b/graphics/mapper/2.0/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4f700c8
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 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.
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.0-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+        "libsync",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+        "libsync",
+    ],
+    header_libs: [
+        "android.hardware.graphics.mapper@2.0-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.mapper@2.0-hal",
+    ],
+    export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.0-passthrough_headers",
+    vendor: true,
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h
new file mode 100644
index 0000000..7369ac7
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Gralloc0Hal.h included without LOG_TAG"
+#endif
+
+#include <inttypes.h>
+
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
+#include <sync/sync.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::BufferUsage;
+
+// Gralloc0HalImpl implements V2_*::hal::MapperHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public Hal {
+   public:
+    bool initWithModule(const hw_module_t* module) {
+        mModule = reinterpret_cast<const gralloc_module_t*>(module);
+        mMinor = module->module_api_version & 0xff;
+        return true;
+    }
+
+    Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                           BufferDescriptor* outDescriptor) override {
+        if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
+            return Error::BAD_VALUE;
+        }
+
+        if (descriptorInfo.layerCount != 1) {
+            return Error::UNSUPPORTED;
+        }
+
+        if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+            return Error::BAD_VALUE;
+        }
+
+        const uint64_t validUsageBits = getValidBufferUsageMask();
+        if (descriptorInfo.usage & ~validUsageBits) {
+            ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+                  descriptorInfo.usage & ~validUsageBits);
+        }
+
+        *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
+
+        return Error::NONE;
+    }
+
+    Error importBuffer(const native_handle_t* rawHandle,
+                       native_handle_t** outBufferHandle) override {
+        native_handle_t* bufferHandle = native_handle_clone(rawHandle);
+        if (!bufferHandle) {
+            return Error::NO_RESOURCES;
+        }
+
+        if (mModule->registerBuffer(mModule, bufferHandle)) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+            return Error::BAD_BUFFER;
+        }
+
+        *outBufferHandle = bufferHandle;
+
+        return Error::NONE;
+    }
+
+    Error freeBuffer(native_handle_t* bufferHandle) override {
+        if (mModule->unregisterBuffer(mModule, bufferHandle)) {
+            return Error::BAD_BUFFER;
+        }
+
+        native_handle_close(bufferHandle);
+        native_handle_delete(bufferHandle);
+        return Error::NONE;
+    }
+
+    Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+               void** outData) override {
+        int result;
+        void* data = nullptr;
+        if (mMinor >= 3 && mModule->lockAsync) {
+            result = mModule->lockAsync(mModule, bufferHandle, cpuUsage, accessRegion.left,
+                                        accessRegion.top, accessRegion.width, accessRegion.height,
+                                        &data, fenceFd.release());
+        } else {
+            waitFenceFd(fenceFd, "Gralloc0Hal::lock");
+
+            result =
+                mModule->lock(mModule, bufferHandle, cpuUsage, accessRegion.left, accessRegion.top,
+                              accessRegion.width, accessRegion.height, &data);
+        }
+
+        if (result) {
+            return Error::BAD_VALUE;
+        }
+
+        *outData = data;
+        return Error::NONE;
+    }
+
+    Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+                    YCbCrLayout* outLayout) override {
+        int result;
+        android_ycbcr ycbcr = {};
+        if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
+            result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
+                                              accessRegion.top, accessRegion.width,
+                                              accessRegion.height, &ycbcr, fenceFd.release());
+        } else {
+            waitFenceFd(fenceFd, "Gralloc0Hal::lockYCbCr");
+
+            if (mModule->lock_ycbcr) {
+                result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
+                                             accessRegion.top, accessRegion.width,
+                                             accessRegion.height, &ycbcr);
+            } else {
+                result = -EINVAL;
+            }
+        }
+
+        if (result) {
+            return Error::BAD_VALUE;
+        }
+
+        outLayout->y = ycbcr.y;
+        outLayout->cb = ycbcr.cb;
+        outLayout->cr = ycbcr.cr;
+        outLayout->yStride = ycbcr.ystride;
+        outLayout->cStride = ycbcr.cstride;
+        outLayout->chromaStep = ycbcr.chroma_step;
+        return Error::NONE;
+    }
+
+    Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
+        int result;
+        int fenceFd = -1;
+        if (mMinor >= 3 && mModule->unlockAsync) {
+            result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
+        } else {
+            result = mModule->unlock(mModule, bufferHandle);
+        }
+
+        // we always own the fenceFd even when unlock failed
+        outFenceFd->reset(fenceFd);
+        return result ? Error::BAD_VALUE : Error::NONE;
+    }
+
+   protected:
+    virtual uint64_t getValidBufferUsageMask() const {
+        return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
+               BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
+               BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
+               BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
+               BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+               BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+               BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK;
+    }
+
+    static void waitFenceFd(const base::unique_fd& fenceFd, const char* logname) {
+        if (fenceFd < 0) {
+            return;
+        }
+
+        const int warningTimeout = 3500;
+        const int error = sync_wait(fenceFd, warningTimeout);
+        if (error < 0 && errno == ETIME) {
+            ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd.get(), warningTimeout);
+            sync_wait(fenceFd, -1);
+        }
+    }
+
+    const gralloc_module_t* mModule = nullptr;
+    uint8_t mMinor = 0;
+};
+
+}  // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::MapperHal>;
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
new file mode 100644
index 0000000..d9beb4f
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
@@ -0,0 +1,338 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Gralloc1Hal.h included without LOG_TAG"
+#endif
+
+#include <inttypes.h>
+
+#include <vector>
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::BufferUsage;
+
+// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public Hal {
+   public:
+    ~Gralloc1HalImpl() {
+        if (mDevice) {
+            gralloc1_close(mDevice);
+        }
+    }
+
+    bool initWithModule(const hw_module_t* module) {
+        int result = gralloc1_open(module, &mDevice);
+        if (result) {
+            ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+            mDevice = nullptr;
+            return false;
+        }
+
+        initCapabilities();
+
+        if (!initDispatch()) {
+            gralloc1_close(mDevice);
+            mDevice = nullptr;
+            return false;
+        }
+
+        return true;
+    }
+
+    Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                           BufferDescriptor* outDescriptor) override {
+        if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
+            return Error::BAD_VALUE;
+        }
+
+        if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount != 1) {
+            return Error::UNSUPPORTED;
+        }
+
+        if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+            return Error::BAD_VALUE;
+        }
+
+        const uint64_t validUsageBits = getValidBufferUsageMask();
+        if (descriptorInfo.usage & ~validUsageBits) {
+            ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+                  descriptorInfo.usage & ~validUsageBits);
+        }
+
+        *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
+
+        return Error::NONE;
+    }
+
+    Error importBuffer(const native_handle_t* rawHandle,
+                       native_handle_t** outBufferHandle) override {
+        native_handle_t* bufferHandle = native_handle_clone(rawHandle);
+        if (!bufferHandle) {
+            return Error::NO_RESOURCES;
+        }
+
+        int32_t error = mDispatch.retain(mDevice, bufferHandle);
+        if (error != GRALLOC1_ERROR_NONE) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+            return toError(error);
+        }
+
+        *outBufferHandle = bufferHandle;
+
+        return Error::NONE;
+    }
+
+    Error freeBuffer(native_handle_t* bufferHandle) override {
+        int32_t error = mDispatch.release(mDevice, bufferHandle);
+        if (error == GRALLOC1_ERROR_NONE && !mCapabilities.releaseImplyDelete) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+        }
+        return toError(error);
+    }
+
+    Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+               void** outData) override {
+        const uint64_t consumerUsage =
+            cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+        const auto accessRect = asGralloc1Rect(accessRegion);
+        void* data = nullptr;
+        int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
+                                       &data, fenceFd.release());
+        if (error == GRALLOC1_ERROR_NONE) {
+            *outData = data;
+        }
+
+        return toError(error);
+    }
+
+    Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+                    YCbCrLayout* outLayout) override {
+        // prepare flex layout
+        android_flex_layout flex = {};
+        int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
+        flex.planes = flexPlanes.data();
+
+        const uint64_t consumerUsage =
+            cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+        const auto accessRect = asGralloc1Rect(accessRegion);
+        error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
+                                   &flex, fenceFd.release());
+        if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
+            ALOGD("unable to convert android_flex_layout to YCbCrLayout");
+            // undo the lock
+            unlock(bufferHandle, &fenceFd);
+            error = GRALLOC1_ERROR_BAD_HANDLE;
+        }
+
+        return toError(error);
+    }
+
+    Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
+        int fenceFd = -1;
+        int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+
+        // we always own the fenceFd even when unlock failed
+        outFenceFd->reset(fenceFd);
+        return toError(error);
+    }
+
+   protected:
+    virtual void initCapabilities() {
+        uint32_t count = 0;
+        mDevice->getCapabilities(mDevice, &count, nullptr);
+
+        std::vector<int32_t> capabilities(count);
+        mDevice->getCapabilities(mDevice, &count, capabilities.data());
+        capabilities.resize(count);
+
+        for (auto capability : capabilities) {
+            switch (capability) {
+                case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+                    mCapabilities.layeredBuffers = true;
+                    break;
+                case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
+                    mCapabilities.releaseImplyDelete = true;
+                    break;
+            }
+        }
+    }
+
+    template <typename T>
+    bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            ALOGE("failed to get gralloc1 function %d", desc);
+            return false;
+        }
+    }
+
+    virtual bool initDispatch() {
+        if (!initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain) ||
+            !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, &mDispatch.getNumFlexPlanes) ||
+            !initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock) ||
+            !initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex) ||
+            !initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    virtual uint64_t getValidBufferUsageMask() const {
+        return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
+               BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
+               BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
+               BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
+               BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+               BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+               BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
+               BufferUsage::VENDOR_MASK_HI;
+    }
+
+    static Error toError(int32_t error) {
+        switch (error) {
+            case GRALLOC1_ERROR_NONE:
+                return Error::NONE;
+            case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+                return Error::BAD_DESCRIPTOR;
+            case GRALLOC1_ERROR_BAD_HANDLE:
+                return Error::BAD_BUFFER;
+            case GRALLOC1_ERROR_BAD_VALUE:
+                return Error::BAD_VALUE;
+            case GRALLOC1_ERROR_NOT_SHARED:
+                return Error::NONE;  // this is fine
+            case GRALLOC1_ERROR_NO_RESOURCES:
+                return Error::NO_RESOURCES;
+            case GRALLOC1_ERROR_UNDEFINED:
+            case GRALLOC1_ERROR_UNSUPPORTED:
+            default:
+                return Error::UNSUPPORTED;
+        }
+    }
+
+    static bool toYCbCrLayout(const android_flex_layout& flex, YCbCrLayout* outLayout) {
+        // must be YCbCr
+        if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
+            return false;
+        }
+
+        for (int i = 0; i < 3; i++) {
+            const auto& plane = flex.planes[i];
+            // must have 8-bit depth
+            if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+                return false;
+            }
+
+            if (plane.component == FLEX_COMPONENT_Y) {
+                // Y must not be interleaved
+                if (plane.h_increment != 1) {
+                    return false;
+                }
+            } else {
+                // Cb and Cr can be interleaved
+                if (plane.h_increment != 1 && plane.h_increment != 2) {
+                    return false;
+                }
+            }
+
+            if (!plane.v_increment) {
+                return false;
+            }
+        }
+
+        if (flex.planes[0].component != FLEX_COMPONENT_Y ||
+            flex.planes[1].component != FLEX_COMPONENT_Cb ||
+            flex.planes[2].component != FLEX_COMPONENT_Cr) {
+            return false;
+        }
+
+        const auto& y = flex.planes[0];
+        const auto& cb = flex.planes[1];
+        const auto& cr = flex.planes[2];
+
+        if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
+            return false;
+        }
+
+        outLayout->y = y.top_left;
+        outLayout->cb = cb.top_left;
+        outLayout->cr = cr.top_left;
+        outLayout->yStride = y.v_increment;
+        outLayout->cStride = cb.v_increment;
+        outLayout->chromaStep = cb.h_increment;
+
+        return true;
+    }
+
+    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect) {
+        return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+    }
+
+    gralloc1_device_t* mDevice = nullptr;
+
+    struct {
+        bool layeredBuffers;
+        bool releaseImplyDelete;
+    } mCapabilities = {};
+
+    struct {
+        GRALLOC1_PFN_RETAIN retain;
+        GRALLOC1_PFN_RELEASE release;
+        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+        GRALLOC1_PFN_LOCK lock;
+        GRALLOC1_PFN_LOCK_FLEX lockFlex;
+        GRALLOC1_PFN_UNLOCK unlock;
+    } mDispatch = {};
+};
+
+}  // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
new file mode 100644
index 0000000..4c477e1
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+/**
+ * BufferDescriptor is created by IMapper and consumed by IAllocator. It is
+ * versioned so that IMapper and IAllocator can be updated independently.
+ */
+constexpr uint32_t grallocBufferDescriptorSize = 7;
+constexpr uint32_t grallocBufferDescriptorMagicVersion = ((0x9487 << 16) | 0);
+
+inline BufferDescriptor grallocEncodeBufferDescriptor(
+    const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    descriptor.resize(grallocBufferDescriptorSize);
+    descriptor[0] = grallocBufferDescriptorMagicVersion;
+    descriptor[1] = descriptorInfo.width;
+    descriptor[2] = descriptorInfo.height;
+    descriptor[3] = descriptorInfo.layerCount;
+    descriptor[4] = static_cast<uint32_t>(descriptorInfo.format);
+    descriptor[5] = static_cast<uint32_t>(descriptorInfo.usage);
+    descriptor[6] = static_cast<uint32_t>(descriptorInfo.usage >> 32);
+
+    return descriptor;
+}
+
+inline bool grallocDecodeBufferDescriptor(const BufferDescriptor& descriptor,
+                                          IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+    if (descriptor.size() != grallocBufferDescriptorSize ||
+        descriptor[0] != grallocBufferDescriptorMagicVersion) {
+        return false;
+    }
+
+    *outDescriptorInfo = IMapper::BufferDescriptorInfo{
+        descriptor[1],
+        descriptor[2],
+        descriptor[3],
+        static_cast<PixelFormat>(descriptor[4]),
+        (static_cast<uint64_t>(descriptor[6]) << 32) | descriptor[5],
+    };
+
+    return true;
+}
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
new file mode 100644
index 0000000..e8b1b4b
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "GrallocLoader.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_set>
+
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/Mapper.h>
+#include <mapper-passthrough/2.0/Gralloc0Hal.h>
+#include <mapper-passthrough/2.0/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+class GrallocImportedBufferPool {
+   public:
+    static GrallocImportedBufferPool& getInstance() {
+        // GraphicBufferMapper in framework is expected to be valid (and
+        // leaked) during process termination.  We need to make sure IMapper,
+        // and in turn, GrallocImportedBufferPool is valid as well.  Create
+        // imported buffer pool on the heap (and let it leak) for the purpose.
+        // Besides, all IMapper instances must share the same pool.  Make it a
+        // singleton.
+        //
+        // However, there is no way to make sure gralloc0/gralloc1 are valid
+        // during process termination.  Any use of static/global object in
+        // gralloc0/gralloc1 that may be destructed during process termination
+        // is potentially broken.
+        static GrallocImportedBufferPool* singleton = new GrallocImportedBufferPool;
+        return *singleton;
+    }
+
+    void* add(native_handle_t* bufferHandle) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
+    }
+
+    native_handle_t* remove(void* buffer) {
+        auto bufferHandle = static_cast<native_handle_t*>(buffer);
+
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
+    }
+
+    const native_handle_t* get(void* buffer) {
+        auto bufferHandle = static_cast<const native_handle_t*>(buffer);
+
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
+    }
+
+   private:
+    std::mutex mMutex;
+    std::unordered_set<const native_handle_t*> mBufferHandles;
+};
+
+// Inherit from V2_*::hal::Mapper and override imported buffer management functions
+template <typename T>
+class GrallocMapper : public T {
+   protected:
+    void* addImportedBuffer(native_handle_t* bufferHandle) override {
+        return GrallocImportedBufferPool::getInstance().add(bufferHandle);
+    }
+
+    native_handle_t* removeImportedBuffer(void* buffer) override {
+        return GrallocImportedBufferPool::getInstance().remove(buffer);
+    }
+
+    const native_handle_t* getImportedBuffer(void* buffer) const override {
+        return GrallocImportedBufferPool::getInstance().get(buffer);
+    }
+};
+
+class GrallocLoader {
+   public:
+    static IMapper* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+        auto hal = createHal(module);
+        if (!hal) {
+            return nullptr;
+        }
+        return createMapper(std::move(hal));
+    }
+
+    // load the gralloc module
+    static const hw_module_t* loadModule() {
+        const hw_module_t* module;
+        int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+        if (error) {
+            ALOGE("failed to get gralloc module");
+            return nullptr;
+        }
+
+        return module;
+    }
+
+    // return the major api version of the module
+    static int getModuleMajorApiVersion(const hw_module_t* module) {
+        return (module->module_api_version >> 8) & 0xff;
+    }
+
+    // create a MapperHal instance
+    static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
+        int major = getModuleMajorApiVersion(module);
+        switch (major) {
+            case 1: {
+                auto hal = std::make_unique<Gralloc1Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            case 0: {
+                auto hal = std::make_unique<Gralloc0Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            default:
+                ALOGE("unknown gralloc module major version %d", major);
+                return nullptr;
+        }
+    }
+
+    // create an IAllocator instance
+    static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
+        auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>();
+        return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android