| /* |
| * 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. |
| */ |
| |
| #include "SensorTest.h" |
| #include <errno.h> |
| |
| namespace android { |
| namespace SensorTest { |
| |
| // SensorTest container class |
| bool SensorTest::SetUp() { |
| if (mManager == nullptr) { |
| mManager.reset( |
| TestSensorManager::getInstanceForPackage("android.hardware.cts.SensorNativeTest")); |
| } |
| return mManager == nullptr; |
| } |
| |
| void SensorTest::TearDown() { |
| if (mManager == nullptr) { |
| mManager.reset(nullptr); |
| } |
| } |
| |
| TestSensorManager::TestSensorManager(const char *package) { |
| mManager = ASensorManager_getInstanceForPackage(package); |
| } |
| |
| TestSensorManager::~TestSensorManager() { |
| for (int channel : mSensorDirectChannel) { |
| destroyDirectChannel(channel); |
| } |
| mSensorDirectChannel.clear(); |
| } |
| |
| TestSensorManager * TestSensorManager::getInstanceForPackage(const char *package) { |
| return new TestSensorManager(package); |
| } |
| |
| TestSensor TestSensorManager::getDefaultSensor(int type) { |
| return TestSensor(ASensorManager_getDefaultSensor(mManager, type)); |
| } |
| |
| int TestSensorManager::createDirectChannel(const TestSharedMemory &mem) { |
| if (!isValid()) { |
| return -EINVAL; |
| } |
| switch (mem.getType()) { |
| case ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY: |
| return createSharedMemoryDirectChannel( |
| mem.getSharedMemoryFd(), mem.getSize()); |
| case ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER: |
| return createHardwareBufferDirectChannel( |
| mem.getHardwareBuffer(), mem.getSize()); |
| default: |
| return -1; |
| } |
| } |
| |
| int TestSensorManager::createSharedMemoryDirectChannel(int fd, size_t size) { |
| int ret = ASensorManager_createSharedMemoryDirectChannel(mManager, fd, size); |
| if (ret > 0) { |
| mSensorDirectChannel.insert(ret); |
| } |
| return ret; |
| } |
| |
| int TestSensorManager::createHardwareBufferDirectChannel( |
| AHardwareBuffer const *buffer, size_t size) { |
| int ret = ASensorManager_createHardwareBufferDirectChannel(mManager, buffer, size); |
| if (ret > 0) { |
| mSensorDirectChannel.insert(ret); |
| } |
| return ret; |
| } |
| |
| void TestSensorManager::destroyDirectChannel(int channel) { |
| if (!isValid()) { |
| return; |
| } |
| ASensorManager_destroyDirectChannel(mManager, channel); |
| mSensorDirectChannel.erase(channel); |
| return; |
| } |
| |
| int TestSensorManager::configureDirectReport(TestSensor sensor, int channel, int rate) { |
| if (!isValid()) { |
| return -EINVAL; |
| } |
| return ASensorManager_configureDirectReport(mManager, sensor, channel, rate); |
| } |
| |
| char * TestSharedMemory::getBuffer() const { |
| return mBuffer; |
| } |
| |
| std::vector<ASensorEvent> TestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const { |
| constexpr size_t kEventSize = sizeof(ASensorEvent); |
| constexpr size_t kOffsetSize = offsetof(ASensorEvent, version); |
| constexpr size_t kOffsetAtomicCounter = offsetof(ASensorEvent, reserved0); |
| |
| std::vector<ASensorEvent> events; |
| while (offset + kEventSize <= mSize) { |
| int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter); |
| if (atomicCounter <= lastCounter) { |
| break; |
| } |
| |
| int32_t size = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetSize); |
| if (size != kEventSize) { |
| // unknown error, events parsed may be wrong, remove all |
| events.clear(); |
| break; |
| } |
| |
| events.push_back(*reinterpret_cast<ASensorEvent *>(mBuffer + offset)); |
| lastCounter = atomicCounter; |
| offset += kEventSize; |
| } |
| |
| return events; |
| } |
| |
| TestSharedMemory::TestSharedMemory(int type, size_t size) |
| : mType(type), mSize(0), mBuffer(nullptr), |
| mSharedMemoryFd(-1), mHardwareBuffer(nullptr) { |
| bool success = false; |
| switch(type) { |
| case ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY: { |
| mSharedMemoryFd = ASharedMemory_create("TestSharedMemory", size); |
| if (mSharedMemoryFd < 0 |
| || ASharedMemory_getSize(mSharedMemoryFd) != size) { |
| break; |
| } |
| |
| mSize = size; |
| mBuffer = reinterpret_cast<char *>(::mmap( |
| nullptr, mSize, PROT_READ | PROT_WRITE, |
| MAP_SHARED, mSharedMemoryFd, 0)); |
| |
| if (mBuffer == MAP_FAILED) { |
| mBuffer = nullptr; |
| break; |
| } |
| success = true; |
| break; |
| } |
| case ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER: { |
| AHardwareBuffer_Desc desc = { |
| .width = static_cast<uint32_t>(size), |
| .height = 1, |
| .layers = 1, |
| .usage = AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA |
| | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, |
| .format = AHARDWAREBUFFER_FORMAT_BLOB |
| }; |
| |
| // allocate |
| if (AHardwareBuffer_allocate(&desc, &mHardwareBuffer) == 0) { |
| // lock |
| if (AHardwareBuffer_lock(mHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, |
| -1, nullptr, reinterpret_cast<void **>(&mBuffer)) == 0) { |
| if (mBuffer != nullptr) { |
| mSize = size; |
| success = true; |
| } |
| } |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| |
| if (!success) { |
| release(); |
| } |
| } |
| |
| TestSharedMemory::~TestSharedMemory() { |
| release(); |
| } |
| |
| void TestSharedMemory::release() { |
| switch(mType) { |
| case ASENSOR_DIRECT_CHANNEL_TYPE_SHARED_MEMORY: { |
| if (mBuffer != nullptr) { |
| ::munmap(mBuffer, mSize); |
| mBuffer = nullptr; |
| } |
| if (mSharedMemoryFd > 0) { |
| ::close(mSharedMemoryFd); |
| mSharedMemoryFd = -1; |
| } |
| mSize = 0; |
| break; |
| } |
| case ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER: { |
| if (mHardwareBuffer != nullptr) { |
| if (mBuffer != nullptr) { |
| int32_t fence = -1; |
| AHardwareBuffer_unlock(mHardwareBuffer, &fence); |
| mBuffer = nullptr; |
| } |
| AHardwareBuffer_release(mHardwareBuffer); |
| mHardwareBuffer = nullptr; |
| } |
| mSize = 0; |
| break; |
| } |
| default: |
| break; |
| } |
| if (mSharedMemoryFd > 0 || mSize != 0 || mBuffer != nullptr || mHardwareBuffer != nullptr) { |
| ALOGE("TestSharedMemory %p not properly destructed: " |
| "type %d, shared_memory_fd %d, hardware_buffer %p, size %zu, buffer %p", |
| this, static_cast<int>(mType), mSharedMemoryFd, mHardwareBuffer, mSize, mBuffer); |
| } |
| } |
| |
| TestSharedMemory* TestSharedMemory::create(int type, size_t size) { |
| constexpr size_t kMaxSize = 128*1024*1024; // sensor test should not need more than 128M |
| if (size == 0 || size >= kMaxSize) { |
| return nullptr; |
| } |
| |
| auto m = new TestSharedMemory(type, size); |
| if (m->mSize != size || m->mBuffer == nullptr) { |
| delete m; |
| m = nullptr; |
| } |
| return m; |
| } |
| } // namespace SensorTest |
| } // namespace android |