summaryrefslogtreecommitdiff
path: root/sensors/common/vts/utils/GrallocWrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sensors/common/vts/utils/GrallocWrapper.cpp')
-rw-r--r--sensors/common/vts/utils/GrallocWrapper.cpp362
1 files changed, 209 insertions, 153 deletions
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index 222ef9611a..1cad9135b7 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -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;
+
+ // IAllocator
+ virtual std::string dumpDebugInfo() = 0;
+ virtual native_handle_t* allocate(uint32_t size) = 0;
+ virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
+
+ // IMapper
+ virtual void* lock(native_handle_t* bufferHandle) = 0;
+ virtual void unlock(native_handle_t* bufferHandle) = 0;
+};
+
+namespace {
+
+bool failed(Error2 error) {
+ return (error != Error2::NONE);
+}
+bool failed(Error3 error) {
+ return (error != Error3::NONE);
}
-void GrallocWrapper::init() {
- mAllocator = allocator2::IAllocator::getService();
- if (mAllocator == nullptr) {
- ALOGE("Failed to get allocator service");
+// 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");
+ }
}
- mMapper = mapper2::IMapper::getService();
- if (mMapper == nullptr) {
- ALOGE("Failed to get mapper service");
- } else if (mMapper->isRemote()) {
- ALOGE("Mapper is not in passthrough mode");
- }
-}
+ virtual std::string dumpDebugInfo() override;
+ virtual native_handle_t* allocate(uint32_t size) override;
+ virtual void freeBuffer(native_handle_t* bufferHandle) override;
-GrallocWrapper::~GrallocWrapper() {
- for (auto bufferHandle : mClonedBuffers) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
- native_handle_close(buffer);
- native_handle_delete(buffer);
- }
- mClonedBuffers.clear();
+ virtual void* lock(native_handle_t* bufferHandle) override;
+ virtual void unlock(native_handle_t* bufferHandle) override;
- 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);
- }
- }
- mImportedBuffers.clear();
-}
+ private:
+ static constexpr uint64_t kBufferUsage =
+ static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN);
+ sp<AllocatorT> mAllocator;
+ sp<MapperT> mMapper;
-sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
- return mAllocator;
-}
+ BufferDescriptor getDescriptor(uint32_t size);
+ native_handle_t* importBuffer(const hidl_handle& rawHandle);
+};
-std::string GrallocWrapper::dumpDebugInfo() {
+template <typename AllocatorT, typename MapperT>
+std::string GrallocHalWrapper<AllocatorT, MapperT>::dumpDebugInfo() {
std::string debugInfo;
- mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
+ 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;
+
+ 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]);
+ }
+ };
- if (bufferHandle) {
- mClonedBuffers.insert(bufferHandle);
- }
+ 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");
- }
- if (count != tmpBuffers.size()) {
- ALOGE("Invalid buffer array");
- }
-
- for (uint32_t i = 0; i < count; i++) {
- if (import) {
- bufferHandles.push_back(importBuffer(tmpBuffers[i]));
- } else {
- bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
- }
- }
-
- if (outStride) {
- *outStride = tmpStride;
- }
- });
-
- return bufferHandles;
-}
-
-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];
-}
-
-sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
- return mMapper;
+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);
+ }
}
-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>
+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 {
+ descriptor = tmpDescriptor;
}
- descriptor = tmpDescriptor;
- });
+ };
+ mMapper->createDescriptor(descriptorInfo, callback);
return descriptor;
}
-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>
+native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::importBuffer(
+ const hidl_handle& rawHandle) {
+ native_handle_t* bufferHandle = nullptr;
+
+ 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);
}
- bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
});
- if (bufferHandle) {
- mImportedBuffers.insert(bufferHandle);
- }
-
return bufferHandle;
}
-void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
+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
- if (mImportedBuffers.erase(bufferHandle)) {
- mapper2::Error error = mMapper->freeBuffer(buffer);
- if (error != mapper2::Error::NONE) {
- ALOGE("Failed to free %p", buffer);
+ 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;
+ }
+ });
+
+ return data;
+}
+
+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));
}
- } 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);
+} // anonymous namespace
- 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;
- }
+GrallocWrapper::GrallocWrapper() {
+ sp<IAllocator3> allocator3 = IAllocator3::getService();
+ sp<IMapper3> mapper3 = IMapper3::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);
- }
- data = tmpData;
- });
+ if (allocator3 != nullptr && mapper3 != nullptr) {
+ mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
+ new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
+ } else {
+ ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
+ (allocator3 != nullptr), (mapper3 != nullptr));
- if (acquireFence >= 0) {
- close(acquireFence);
- }
+ sp<IAllocator2> allocator2 = IAllocator2::getService();
+ sp<IMapper2> mapper2 = IMapper2_1::getService();
+ if (mapper2 == nullptr) {
+ mapper2 = IMapper2::getService();
+ }
- return data;
+ 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));
+ }
+ }
}
-int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
- auto buffer = const_cast<native_handle_t*>(bufferHandle);
+GrallocWrapper::~GrallocWrapper() {
+ for (auto bufferHandle : mAllocatedBuffers) {
+ mGrallocHal->unlock(bufferHandle);
+ mGrallocHal->freeBuffer(bufferHandle);
+ }
+ mAllocatedBuffers.clear();
+}
- int releaseFence = -1;
- mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
- if (tmpError != mapper2::Error::NONE) {
- ALOGE("Failed to unlock buffer %p", buffer);
- }
+std::string GrallocWrapper::dumpDebugInfo() {
+ return mGrallocHal->dumpDebugInfo();
+}
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle) {
- if (fenceHandle->numInts != 0) {
- ALOGE("Invalid fence handle %p", fenceHandle);
- }
- if (fenceHandle->numFds == 1) {
- releaseFence = dup(fenceHandle->data[0]);
- if (releaseFence < 0) {
- ALOGE("Failed to dup fence fd");
- }
- } else {
- if (fenceHandle->numFds != 0) {
- ALOGE("Invalid fence handle %p", fenceHandle);
- }
- }
+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 {
+ 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