Merge "Sensor direct report test - gralloc support"
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index a49307d..fb8d22e 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 0000000..e422d62
--- /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 <utils/Log.h>
+
+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<native_handle_t*>(bufferHandle);
+ native_handle_close(buffer);
+ native_handle_delete(buffer);
+ }
+ mClonedBuffers.clear();
+
+ 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();
+}
+
+sp<allocator2::IAllocator> 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<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);
+ ALOGE("QQ");
+ auto buffers = allocate(descriptor, 1, import, outStride);
+ return buffers[0];
+}
+
+sp<mapper2::IMapper> 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<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);
+
+ 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<native_handle_t*>(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<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);
+ }
+
+ 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 0000000..e506fe1
--- /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 <unordered_set>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+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<allocator2::IAllocator> getAllocator() const;
+ sp<mapper2::IMapper> 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<const native_handle_t*> 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<allocator2::IAllocator> mAllocator;
+ sp<mapper2::IMapper> 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<const native_handle_t*> mClonedBuffers;
+ std::unordered_set<const native_handle_t*> 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 4842946..19265c2 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 <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/sensors/1.0/ISensors.h>
@@ -36,6 +37,7 @@
#include <sys/mman.h>
#include <unistd.h>
+using ::android::GrallocWrapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_string;
@@ -230,6 +232,7 @@
native_handle_t* mNativeHandle;
size_t mSize;
char* mBuffer;
+ std::unique_ptr<GrallocWrapper> mGrallocWrapper;
DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
};
@@ -265,6 +268,7 @@
while (offset + kEventSize <= mSize) {
int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter);
if (atomicCounter <= lastCounter) {
+ ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, lastCounter);
break;
}
@@ -324,7 +328,34 @@
break;
}
case SharedMemType::GRALLOC: {
+ mGrallocWrapper = std::make_unique<GrallocWrapper>();
+ 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<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;
+ }
break;
}
default:
@@ -353,6 +384,16 @@
}
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 @@
void SensorsHidlTest::testDirectReportOperation(
SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) {
constexpr size_t kEventSize = static_cast<size_t>(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 @@
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);