From c1fcb010d7e4f71930e48cfb3e34327ba0a2e46d Mon Sep 17 00:00:00 2001 From: Peng Xu Date: Mon, 21 Aug 2017 18:35:28 -0700 Subject: [PATCH] Sensor direct report test - gralloc support Bug: 37794556 Test: sensor vts passes on 2016 and 2017 devices Change-Id: Ibe1d076c24dc2cfe61dfd19aa5055c9075aa9e14 Merged-In: Ibe1d076c24dc2cfe61dfd19aa5055c9075aa9e14 --- sensors/1.0/vts/functional/Android.bp | 11 +- sensors/1.0/vts/functional/GrallocWrapper.cpp | 232 ++++++++++++++++++ sensors/1.0/vts/functional/GrallocWrapper.h | 80 ++++++ .../VtsHalSensorsV1_0TargetTest.cpp | 97 +++++++- 4 files changed, 417 insertions(+), 3 deletions(-) create mode 100644 sensors/1.0/vts/functional/GrallocWrapper.cpp create mode 100644 sensors/1.0/vts/functional/GrallocWrapper.h diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp index a49307da1d..fb8d22ec48 100644 --- a/sensors/1.0/vts/functional/Android.bp +++ b/sensors/1.0/vts/functional/Android.bp @@ -17,7 +17,14 @@ cc_test { name: "VtsHalSensorsV1_0TargetTest", defaults: ["VtsHalTargetTestDefaults"], - srcs: ["VtsHalSensorsV1_0TargetTest.cpp"], - static_libs: ["android.hardware.sensors@1.0"], + srcs: [ + "GrallocWrapper.cpp", + "VtsHalSensorsV1_0TargetTest.cpp" + ], + static_libs: [ + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.sensors@1.0" + ] } diff --git a/sensors/1.0/vts/functional/GrallocWrapper.cpp b/sensors/1.0/vts/functional/GrallocWrapper.cpp new file mode 100644 index 0000000000..e422d62c72 --- /dev/null +++ b/sensors/1.0/vts/functional/GrallocWrapper.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (C) 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. + */ + +#define LOG_TAG "GrallocWrapper" + +#include "GrallocWrapper.h" + +#include + +namespace android { + +GrallocWrapper::GrallocWrapper() { init(); } + +void GrallocWrapper::init() { + mAllocator = allocator2::IAllocator::getService(); + if (mAllocator == nullptr) { + ALOGE("Failed to get allocator service"); + } + + mMapper = mapper2::IMapper::getService(); + if (mMapper == nullptr) { + ALOGE("Failed to get mapper service"); + } + if (mMapper->isRemote()) { + ALOGE("Mapper is not in passthrough mode"); + } +} + +GrallocWrapper::~GrallocWrapper() { + for (auto bufferHandle : mClonedBuffers) { + auto buffer = const_cast(bufferHandle); + native_handle_close(buffer); + native_handle_delete(buffer); + } + mClonedBuffers.clear(); + + for (auto bufferHandle : mImportedBuffers) { + auto buffer = const_cast(bufferHandle); + if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) { + ALOGE("Failed to free buffer %p", buffer); + } + } + mImportedBuffers.clear(); +} + +sp GrallocWrapper::getAllocator() const { + return mAllocator; +} + +std::string GrallocWrapper::dumpDebugInfo() { + std::string debugInfo; + mAllocator->dumpDebugInfo( + [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); + + return debugInfo; +} + +const native_handle_t* GrallocWrapper::cloneBuffer( + const hardware::hidl_handle& rawHandle) { + const native_handle_t* bufferHandle = + native_handle_clone(rawHandle.getNativeHandle()); + + if (bufferHandle) { + mClonedBuffers.insert(bufferHandle); + } + return bufferHandle; +} + +std::vector GrallocWrapper::allocate( + const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, + uint32_t* outStride) { + std::vector 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); + ALOGE("QQ"); + auto buffers = allocate(descriptor, 1, import, outStride); + return buffers[0]; +} + +sp GrallocWrapper::getMapper() const { return mMapper; } + +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"); + } + descriptor = tmpDescriptor; + }); + + 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()); + } + bufferHandle = static_cast(tmpBuffer); + }); + + if (bufferHandle) { + mImportedBuffers.insert(bufferHandle); + } + + return bufferHandle; +} + +void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) { + auto buffer = const_cast(bufferHandle); + + if (mImportedBuffers.erase(bufferHandle)) { + mapper2::Error error = mMapper->freeBuffer(buffer); + if (error != mapper2::Error::NONE) { + ALOGE("Failed to free %p", buffer); + } + } 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(bufferHandle); + + 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; + } + + 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 (acquireFence >= 0) { + close(acquireFence); + } + + return data; +} + +int GrallocWrapper::unlock(const native_handle_t* bufferHandle) { + auto buffer = const_cast(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); + } + + 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); + } + } + } + }); + + return releaseFence; +} + +} // namespace android diff --git a/sensors/1.0/vts/functional/GrallocWrapper.h b/sensors/1.0/vts/functional/GrallocWrapper.h new file mode 100644 index 0000000000..e506fe1d86 --- /dev/null +++ b/sensors/1.0/vts/functional/GrallocWrapper.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 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. + */ + +#ifndef GRALLO_WRAPPER_H_ +#define GRALLO_WRAPPER_H_ + +#include + +#include +#include + +namespace allocator2 = ::android::hardware::graphics::allocator::V2_0; +namespace mapper2 = ::android::hardware::graphics::mapper::V2_0; + +namespace android { + +// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/ +class GrallocWrapper { + public: + GrallocWrapper(); + ~GrallocWrapper(); + + sp getAllocator() const; + sp getMapper() const; + + std::string dumpDebugInfo(); + + // When import is false, this simply calls IAllocator::allocate. When import + // is true, the returned buffers are also imported into the mapper. + // + // Either case, the returned buffers must be freed with freeBuffer. + std::vector allocate( + const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import = true, + uint32_t* outStride = nullptr); + const native_handle_t* allocate( + const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true, + uint32_t* outStride = nullptr); + + mapper2::BufferDescriptor createDescriptor( + const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo); + + const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle); + void freeBuffer(const native_handle_t* bufferHandle); + + // We use fd instead of hardware::hidl_handle in these functions to pass fences + // in and out of the mapper. The ownership of the fd is always transferred + // with each of these functions. + void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, + const mapper2::IMapper::Rect& accessRegion, int acquireFence); + + int unlock(const native_handle_t* bufferHandle); + + private: + void init(); + const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle); + + sp mAllocator; + sp mMapper; + + // Keep track of all cloned and imported handles. When a test fails with + // ASSERT_*, the destructor will free the handles for the test. + std::unordered_set mClonedBuffers; + std::unordered_set mImportedBuffers; +}; + +} // namespace android +#endif // GRALLO_WRAPPER_H_ diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp index 48429466e7..19265c2916 100644 --- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp +++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp @@ -15,6 +15,7 @@ */ #define LOG_TAG "sensors_hidl_hal_test" +#include "GrallocWrapper.h" #include #include #include @@ -36,6 +37,7 @@ #include #include +using ::android::GrallocWrapper; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::hidl_string; @@ -230,6 +232,7 @@ class SensorsTestSharedMemory { native_handle_t* mNativeHandle; size_t mSize; char* mBuffer; + std::unique_ptr mGrallocWrapper; DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory); }; @@ -265,6 +268,7 @@ std::vector SensorsTestSharedMemory::parseEvents(int64_t lastCounter, siz while (offset + kEventSize <= mSize) { int64_t atomicCounter = *reinterpret_cast(mBuffer + offset + kOffsetAtomicCounter); if (atomicCounter <= lastCounter) { + ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, lastCounter); break; } @@ -324,7 +328,34 @@ SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size break; } case SharedMemType::GRALLOC: { + mGrallocWrapper = std::make_unique(); + if (mGrallocWrapper->getAllocator() == nullptr || mGrallocWrapper->getMapper() == nullptr) { + 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(size), + .height = 1, + .layerCount = 1, + .usage = static_cast (BufferUsage::SENSOR_DIRECT_DATA | + BufferUsage::CPU_READ_OFTEN), + .format = PixelFormat::BLOB + }; + handle = const_cast(mGrallocWrapper->allocate(buf_desc_info)); + if (handle != nullptr) { + mapper2::IMapper::Rect region{0, 0, + static_cast(buf_desc_info.width), + static_cast(buf_desc_info.height)}; + buffer = static_cast + (mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1)); + if (buffer != nullptr) { + break; + } + mGrallocWrapper->freeBuffer(handle); + handle = nullptr; + } break; } default: @@ -353,6 +384,16 @@ SensorsTestSharedMemory::~SensorsTestSharedMemory() { } break; } + case SharedMemType::GRALLOC: { + if (mSize != 0) { + mGrallocWrapper->unlock(mNativeHandle); + mGrallocWrapper->freeBuffer(mNativeHandle); + + mNativeHandle = nullptr; + mSize = 0; + } + break; + } default: { if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) { ALOGE("SensorsTestSharedMemory %p not properly destructed: " @@ -1223,7 +1264,7 @@ TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) { void SensorsHidlTest::testDirectReportOperation( SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) { constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); - constexpr size_t kNEvent = 500; + constexpr size_t kNEvent = 4096; constexpr size_t kMemSize = kEventSize * kNEvent; constexpr float kNormalNominal = 50; @@ -1379,6 +1420,60 @@ TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) { SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::VERY_FAST, NullChecker()); } +// Test sensor event direct report with gralloc for accel sensor at normal rate +TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) { + testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL, + sAccelNormChecker); +} + +// Test sensor event direct report with gralloc for accel sensor at fast rate +TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) { + testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST, + sAccelNormChecker); +} + +// Test sensor event direct report with gralloc for accel sensor at very fast rate +TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) { + testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::VERY_FAST, + sAccelNormChecker); +} + +// Test sensor event direct report with gralloc for gyro sensor at normal rate +TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) { + testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL, + sGyroNormChecker); +} + +// Test sensor event direct report with gralloc for gyro sensor at fast rate +TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) { + testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST, + sGyroNormChecker); +} + +// Test sensor event direct report with gralloc for gyro sensor at very fast rate +TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) { + testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST, + sGyroNormChecker); +} + +// Test sensor event direct report with gralloc for mag sensor at normal rate +TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) { + testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL, + NullChecker()); +} + +// Test sensor event direct report with gralloc for mag sensor at fast rate +TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) { + testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST, + NullChecker()); +} + +// Test sensor event direct report with gralloc for mag sensor at very fast rate +TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) { + testDirectReportOperation( + SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::VERY_FAST, NullChecker()); +} + int main(int argc, char **argv) { ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv);