Merge "Sensor direct report test - gralloc support"

am: b7841f02e2

Change-Id: I815c61af5b807fd9a8ebd9d7ccf2842a60f1a1f6
This commit is contained in:
Peng Xu 2017-09-12 20:09:59 +00:00 committed by android-build-merger
commit 4ff424ce6c
4 changed files with 417 additions and 3 deletions

View file

@ -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"
]
}

View file

@ -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

View file

@ -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_

View file

@ -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 @@ class SensorsTestSharedMemory {
native_handle_t* mNativeHandle;
size_t mSize;
char* mBuffer;
std::unique_ptr<GrallocWrapper> mGrallocWrapper;
DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
};
@ -265,6 +268,7 @@ std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, siz
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 @@ SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size
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 @@ 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<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;
@ -1384,6 +1425,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);