Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ddbcc0e authored by Brian Duddie's avatar Brian Duddie Committed by android-build-merger
Browse files

Add support for new gralloc HAL versions

am: df6e2b70

Change-Id: Ibc9eb61aae2239fd625d4a9ca840cb0d41b2c8ca
parents 0ef0800d df6e2b70
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -24,7 +24,10 @@ cc_test {
    ],
    static_libs: [
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.allocator@3.0",
        "android.hardware.graphics.mapper@2.0",
        "android.hardware.graphics.mapper@2.1",
        "android.hardware.graphics.mapper@3.0",
        "android.hardware.sensors@1.0",
        "VtsHalSensorsTargetTestUtils",
    ],
+3 −0
Original line number Diff line number Diff line
@@ -24,7 +24,10 @@ cc_test {
    ],
    static_libs: [
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.allocator@3.0",
        "android.hardware.graphics.mapper@2.0",
        "android.hardware.graphics.mapper@2.1",
        "android.hardware.graphics.mapper@3.0",
        "android.hardware.sensors@1.0",
        "android.hardware.sensors@2.0",
        "libfmq",
+3 −0
Original line number Diff line number Diff line
@@ -31,7 +31,10 @@ cc_library_static {
    ],
    static_libs: [
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.allocator@3.0",
        "android.hardware.graphics.mapper@2.0",
        "android.hardware.graphics.mapper@2.1",
        "android.hardware.graphics.mapper@3.0",
        "android.hardware.sensors@1.0",
        "VtsHalHidlTargetTestBase",
    ],
+209 −153
Original line number Diff line number Diff line
@@ -16,206 +16,262 @@

#include "GrallocWrapper.h"

#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <android/hardware/graphics/mapper/2.1/IMapper.h>
#include <android/hardware/graphics/mapper/3.0/IMapper.h>

#include <utils/Log.h>

#include <cinttypes>
#include <type_traits>

using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;

using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;

using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;

// This is a typedef to the same underlying type across v2.0 and v3.0
using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;

using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;

namespace android {

GrallocWrapper::GrallocWrapper() {
    init();
}
// Since we use the same APIs across allocator/mapper HALs but they have major
// version differences (meaning they are not related through inheritance), we
// create a common interface abstraction for the IAllocator + IMapper combination
// (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to
// be paired with IMapper 3.0, so these are tied together)
class IGrallocHalWrapper {
  public:
    virtual ~IGrallocHalWrapper() = default;

void GrallocWrapper::init() {
    mAllocator = allocator2::IAllocator::getService();
    if (mAllocator == nullptr) {
        ALOGE("Failed to get allocator service");
    }
    // IAllocator
    virtual std::string dumpDebugInfo() = 0;
    virtual native_handle_t* allocate(uint32_t size) = 0;
    virtual void freeBuffer(native_handle_t* bufferHandle) = 0;

    mMapper = mapper2::IMapper::getService();
    if (mMapper == nullptr) {
        ALOGE("Failed to get mapper service");
    } else if (mMapper->isRemote()) {
        ALOGE("Mapper is not in passthrough mode");
    }
}
    // IMapper
    virtual void* lock(native_handle_t* bufferHandle) = 0;
    virtual void unlock(native_handle_t* bufferHandle) = 0;
};

GrallocWrapper::~GrallocWrapper() {
    for (auto bufferHandle : mClonedBuffers) {
        auto buffer = const_cast<native_handle_t*>(bufferHandle);
        native_handle_close(buffer);
        native_handle_delete(buffer);
    }
    mClonedBuffers.clear();
namespace {

    for (auto bufferHandle : mImportedBuffers) {
        auto buffer = const_cast<native_handle_t*>(bufferHandle);
        if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
            ALOGE("Failed to free buffer %p", buffer);
        }
bool failed(Error2 error) {
    return (error != Error2::NONE);
}
    mImportedBuffers.clear();
bool failed(Error3 error) {
    return (error != Error3::NONE);
}

sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
    return mAllocator;
// Since all the type and function names are the same for the things we use across the major HAL
// versions, we use template magic to avoid repeating ourselves.
template <typename AllocatorT, typename MapperT>
class GrallocHalWrapper : public IGrallocHalWrapper {
  public:
    GrallocHalWrapper(const sp<AllocatorT>& allocator, const sp<MapperT>& mapper)
        : mAllocator(allocator), mMapper(mapper) {
        if (mapper->isRemote()) {
            ALOGE("Mapper is in passthrough mode");
        }
    }

std::string GrallocWrapper::dumpDebugInfo() {
    std::string debugInfo;
    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
    virtual std::string dumpDebugInfo() override;
    virtual native_handle_t* allocate(uint32_t size) override;
    virtual void freeBuffer(native_handle_t* bufferHandle) override;

    virtual void* lock(native_handle_t* bufferHandle) override;
    virtual void unlock(native_handle_t* bufferHandle) override;

  private:
    static constexpr uint64_t kBufferUsage =
            static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
    sp<AllocatorT> mAllocator;
    sp<MapperT> mMapper;

    BufferDescriptor getDescriptor(uint32_t size);
    native_handle_t* importBuffer(const hidl_handle& rawHandle);
};

template <typename AllocatorT, typename MapperT>
std::string GrallocHalWrapper<AllocatorT, MapperT>::dumpDebugInfo() {
    std::string debugInfo;
    mAllocator->dumpDebugInfo([&](const hidl_string& tmpDebugInfo) { debugInfo = tmpDebugInfo; });
    return debugInfo;
}

const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) {
    const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
template <typename AllocatorT, typename MapperT>
native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::allocate(uint32_t size) {
    constexpr uint32_t kBufferCount = 1;
    BufferDescriptor descriptor = getDescriptor(size);
    native_handle_t* bufferHandle = nullptr;

    if (bufferHandle) {
        mClonedBuffers.insert(bufferHandle);
    auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
        if (failed(error)) {
            ALOGE("Failed to allocate buffer: %" PRId32, static_cast<int32_t>(error));
        } else if (buffers.size() != kBufferCount) {
            ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(),
                  kBufferCount);
        } else {
            bufferHandle = importBuffer(buffers[0]);
        }
    };

    mAllocator->allocate(descriptor, kBufferCount, callback);
    return bufferHandle;
}

std::vector<const native_handle_t*> GrallocWrapper::allocate(
    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) {
    std::vector<const native_handle_t*> bufferHandles;
    bufferHandles.reserve(count);
    mAllocator->allocate(descriptor, count,
                         [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
                             if (mapper2::Error::NONE != tmpError) {
                                 ALOGE("Failed to allocate buffers");
template <typename AllocatorT, typename MapperT>
void GrallocHalWrapper<AllocatorT, MapperT>::freeBuffer(native_handle_t* bufferHandle) {
    auto error = mMapper->freeBuffer(bufferHandle);
    if (!error.isOk() || failed(error)) {
        ALOGE("Failed to free buffer %p", bufferHandle);
    }
                             if (count != tmpBuffers.size()) {
                                 ALOGE("Invalid buffer array");
}

                             for (uint32_t i = 0; i < count; i++) {
                                 if (import) {
                                     bufferHandles.push_back(importBuffer(tmpBuffers[i]));
template <typename AllocatorT, typename MapperT>
BufferDescriptor GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
    typename MapperT::BufferDescriptorInfo descriptorInfo = {
            .width = size,
            .height = 1,
            .layerCount = 1,
            .usage = kBufferUsage,
            .format = static_cast<decltype(descriptorInfo.format)>(PixelFormat::BLOB),
    };

    BufferDescriptor descriptor;
    auto callback = [&](auto error, const BufferDescriptor& tmpDescriptor) {
        if (failed(error)) {
            ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
        } else {
                                     bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
                                 }
            descriptor = tmpDescriptor;
        }
    };

                             if (outStride) {
                                 *outStride = tmpStride;
    mMapper->createDescriptor(descriptorInfo, callback);
    return descriptor;
}
                         });

    return bufferHandles;
}
template <typename AllocatorT, typename MapperT>
native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::importBuffer(
        const hidl_handle& rawHandle) {
    native_handle_t* bufferHandle = nullptr;

const native_handle_t* GrallocWrapper::allocate(
    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
    uint32_t* outStride) {
    mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
    auto buffers = allocate(descriptor, 1, import, outStride);
    return buffers[0];
    mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) {
        if (failed(error)) {
            ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(),
                  static_cast<int32_t>(error));
        } else {
            bufferHandle = static_cast<native_handle_t*>(tmpBuffer);
        }
    });

sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
    return mMapper;
    return bufferHandle;
}

mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
    mapper2::BufferDescriptor descriptor;
    mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
        if (tmpError != mapper2::Error::NONE) {
            ALOGE("Failed to create descriptor");
template <typename AllocatorT, typename MapperT>
void* GrallocHalWrapper<AllocatorT, MapperT>::lock(native_handle_t* bufferHandle) {
    // Per the HAL, all-zeros Rect means the entire buffer
    typename MapperT::Rect accessRegion = {};
    hidl_handle acquireFenceHandle;  // No fence needed, already safe to lock

    void* data = nullptr;
    mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
                  [&](auto error, void* tmpData, ...) {  // V3_0 passes extra args we don't use
                      if (failed(error)) {
                          ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
                                static_cast<int32_t>(error));
                      } else {
                          data = tmpData;
                      }
        descriptor = tmpDescriptor;
                  });

    return descriptor;
    return data;
}

const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) {
    const native_handle_t* bufferHandle = nullptr;
    mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
        if (tmpError != mapper2::Error::NONE) {
            ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
template <typename AllocatorT, typename MapperT>
void GrallocHalWrapper<AllocatorT, MapperT>::unlock(native_handle_t* bufferHandle) {
    mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) {
        if (failed(error)) {
            ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle,
                  static_cast<int32_t>(error));
        }
        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
    });

    if (bufferHandle) {
        mImportedBuffers.insert(bufferHandle);
}

    return bufferHandle;
}
}  // anonymous namespace

void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);
GrallocWrapper::GrallocWrapper() {
    sp<IAllocator3> allocator3 = IAllocator3::getService();
    sp<IMapper3> mapper3 = IMapper3::getService();

    if (mImportedBuffers.erase(bufferHandle)) {
        mapper2::Error error = mMapper->freeBuffer(buffer);
        if (error != mapper2::Error::NONE) {
            ALOGE("Failed to free %p", buffer);
        }
    if (allocator3 != nullptr && mapper3 != nullptr) {
        mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
                new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
    } else {
        mClonedBuffers.erase(bufferHandle);
        native_handle_close(buffer);
        native_handle_delete(buffer);
    }
}

void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
                           const mapper2::IMapper::Rect& accessRegion, int acquireFence) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);
        ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
              (allocator3 != nullptr), (mapper3 != nullptr));

    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
    hardware::hidl_handle acquireFenceHandle;
    if (acquireFence >= 0) {
        auto h = native_handle_init(acquireFenceStorage, 1, 0);
        h->data[0] = acquireFence;
        acquireFenceHandle = h;
        sp<IAllocator2> allocator2 = IAllocator2::getService();
        sp<IMapper2> mapper2 = IMapper2_1::getService();
        if (mapper2 == nullptr) {
            mapper2 = IMapper2::getService();
        }

    void* data = nullptr;
    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
                  [&](const auto& tmpError, const auto& tmpData) {
                      if (tmpError != mapper2::Error::NONE) {
                          ALOGE("Failed to lock buffer %p", buffer);
        if (allocator2 != nullptr && mapper2 != nullptr) {
            mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
                    new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
        } else {
            ALOGE("Couldn't open 2.x/3.0 graphics HALs (2.x allocator %d mapper %d)",
                  (allocator2 != nullptr), (mapper2 != nullptr));
        }
                      data = tmpData;
                  });

    if (acquireFence >= 0) {
        close(acquireFence);
    }

    return data;
}

int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);

    int releaseFence = -1;
    mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
        if (tmpError != mapper2::Error::NONE) {
            ALOGE("Failed to unlock buffer %p", buffer);
GrallocWrapper::~GrallocWrapper() {
    for (auto bufferHandle : mAllocatedBuffers) {
        mGrallocHal->unlock(bufferHandle);
        mGrallocHal->freeBuffer(bufferHandle);
    }

        auto fenceHandle = tmpReleaseFence.getNativeHandle();
        if (fenceHandle) {
            if (fenceHandle->numInts != 0) {
                ALOGE("Invalid fence handle %p", fenceHandle);
    mAllocatedBuffers.clear();
}
            if (fenceHandle->numFds == 1) {
                releaseFence = dup(fenceHandle->data[0]);
                if (releaseFence < 0) {
                    ALOGE("Failed to dup fence fd");

std::string GrallocWrapper::dumpDebugInfo() {
    return mGrallocHal->dumpDebugInfo();
}

std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
    native_handle_t* bufferHandle = mGrallocHal->allocate(size);
    void* buffer = nullptr;
    if (bufferHandle) {
        buffer = mGrallocHal->lock(bufferHandle);
        if (buffer) {
            mAllocatedBuffers.insert(bufferHandle);
        } else {
                if (fenceHandle->numFds != 0) {
                    ALOGE("Invalid fence handle %p", fenceHandle);
            mGrallocHal->freeBuffer(bufferHandle);
            bufferHandle = nullptr;
        }
    }
    return std::make_pair<>(bufferHandle, buffer);
}
    });

    return releaseFence;
void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) {
    if (mAllocatedBuffers.erase(bufferHandle)) {
        mGrallocHal->unlock(bufferHandle);
        mGrallocHal->freeBuffer(bufferHandle);
    }
}

}  // namespace android
+5 −26
Original line number Diff line number Diff line
@@ -119,32 +119,13 @@ SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size
        }
        case SharedMemType::GRALLOC: {
            mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
            if (mGrallocWrapper->getAllocator() == nullptr ||
                mGrallocWrapper->getMapper() == nullptr) {
            if (!mGrallocWrapper->isInitialized()) {
                break;
            }
            using android::hardware::graphics::common::V1_0::BufferUsage;
            using android::hardware::graphics::common::V1_0::PixelFormat;
            mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
                .width = static_cast<uint32_t>(size),
                .height = 1,
                .layerCount = 1,
                .usage = static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA |
                                               BufferUsage::CPU_READ_OFTEN),
                .format = PixelFormat::BLOB};

            handle = const_cast<native_handle_t*>(mGrallocWrapper->allocate(buf_desc_info));
            if (handle != nullptr) {
                mapper2::IMapper::Rect region{0, 0, static_cast<int32_t>(buf_desc_info.width),
                                              static_cast<int32_t>(buf_desc_info.height)};
                buffer = static_cast<char*>(
                    mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
                if (buffer != nullptr) {
                    break;
                }
                mGrallocWrapper->freeBuffer(handle);
                handle = nullptr;
            }

            std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size);
            handle = buf.first;
            buffer = static_cast<char*>(buf.second);
            break;
        }
        default:
@@ -175,9 +156,7 @@ SensorsTestSharedMemory::~SensorsTestSharedMemory() {
        }
        case SharedMemType::GRALLOC: {
            if (mSize != 0) {
                mGrallocWrapper->unlock(mNativeHandle);
                mGrallocWrapper->freeBuffer(mNativeHandle);

                mNativeHandle = nullptr;
                mSize = 0;
            }
Loading