Loading sensors/aidl/vts/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ cc_test { shared_libs: [ "libbinder", "libbinder_ndk", "libvndksupport", "libfmq", "android.hardware.common-V2-ndk", "android.hardware.common.fmq-V1-ndk", Loading @@ -41,6 +42,7 @@ cc_test { static_libs: [ "android.hardware.sensors-V1-ndk", "VtsHalSensorsTargetTestUtils", "libaidlcommonsupport", ], test_suites: [ "general-tests", Loading sensors/aidl/vts/SensorsAidlTestSharedMemory.h 0 → 100644 +218 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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 ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H #define ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H #include "sensors-vts-utils/GrallocWrapper.h" #include <aidlcommonsupport/NativeHandle.h> #include <android-base/macros.h> #include <log/log.h> #include <sys/mman.h> #include <cinttypes> #include <cutils/ashmem.h> using ::aidl::android::hardware::sensors::BnSensors; using ::aidl::android::hardware::sensors::Event; using ::aidl::android::hardware::sensors::ISensors; using ::aidl::android::hardware::sensors::SensorType; template <class SensorType, class Event> class SensorsAidlTestSharedMemory { public: static SensorsAidlTestSharedMemory* create(ISensors::SharedMemInfo::SharedMemType 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 SensorsAidlTestSharedMemory<SensorType, Event>(type, size); if (m->mSize != size || m->mBuffer == nullptr) { delete m; m = nullptr; } return m; } ISensors::SharedMemInfo getSharedMemInfo() const { ISensors::SharedMemInfo mem = { .type = mType, .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT, .size = static_cast<int32_t>(mSize), .memoryHandle = android::dupToAidl(mNativeHandle)}; return mem; } char* getBuffer() const { return mBuffer; } size_t getSize() const { return mSize; } std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const { constexpr size_t kEventSize = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH); constexpr size_t kOffsetSize = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD); constexpr size_t kOffsetToken = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN); constexpr size_t kOffsetType = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE); constexpr size_t kOffsetAtomicCounter = static_cast<size_t>( BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER); constexpr size_t kOffsetTimestamp = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP); constexpr size_t kOffsetData = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA); std::vector<Event> events; std::vector<float> data(16); 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; } 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; } int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken); int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType); int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp); ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32 ", timestamp %" PRId64, offset, atomicCounter, token, type, timestamp); Event event = { .timestamp = timestamp, .sensorHandle = token, .sensorType = type, }; event.set<Event::Data>(reinterpret_cast<float*>(mBuffer + offset + kOffsetData)); // event.u.data = android::hardware::hidl_array<float, // 16>(reinterpret_cast<float*>(mBuffer + offset + kOffsetData)); events.push_back(event); lastCounter = atomicCounter; offset += kEventSize; } return events; } virtual ~SensorsAidlTestSharedMemory() { switch (mType) { case ISensors::SharedMemInfo::SharedMemType::ASHMEM: { if (mSize != 0) { ::munmap(mBuffer, mSize); mBuffer = nullptr; ::native_handle_close(mNativeHandle); ::native_handle_delete(mNativeHandle); mNativeHandle = nullptr; mSize = 0; } break; } case ISensors::SharedMemInfo::SharedMemType::GRALLOC: { if (mSize != 0) { mGrallocWrapper->freeBuffer(mNativeHandle); mNativeHandle = nullptr; mSize = 0; } break; } default: { if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) { ALOGE("SensorsAidlTestSharedMemory %p not properly destructed: " "type %d, native handle %p, size %zu, buffer %p", this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer); } break; } } } private: SensorsAidlTestSharedMemory(ISensors::SharedMemInfo::SharedMemType type, size_t size) : mType(type), mSize(0), mBuffer(nullptr) { native_handle_t* handle = nullptr; char* buffer = nullptr; switch (type) { case ISensors::SharedMemInfo::SharedMemType::ASHMEM: { int fd; handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/); if (handle != nullptr) { handle->data[0] = fd = ::ashmem_create_region("SensorsAidlTestSharedMemory", size); if (handle->data[0] > 0) { // memory is pinned by default buffer = static_cast<char*>( ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); if (buffer != reinterpret_cast<char*>(MAP_FAILED)) { break; } ::native_handle_close(handle); } ::native_handle_delete(handle); handle = nullptr; } break; } case ISensors::SharedMemInfo::SharedMemType::GRALLOC: { mGrallocWrapper = std::make_unique<::android::GrallocWrapper>(); if (!mGrallocWrapper->isInitialized()) { break; } std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size); handle = buf.first; buffer = static_cast<char*>(buf.second); break; } default: break; } if (buffer != nullptr) { mNativeHandle = handle; mSize = size; mBuffer = buffer; } } ISensors::SharedMemInfo::SharedMemType mType; native_handle_t* mNativeHandle; size_t mSize; char* mBuffer; std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper; DISALLOW_COPY_AND_ASSIGN(SensorsAidlTestSharedMemory); }; #endif // ANDROID_SENSORS_TEST_SHARED_MEMORY_H sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp +196 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <utils/SystemClock.h> #include "SensorsAidlEnvironment.h" #include "SensorsAidlTestSharedMemory.h" #include "sensors-vts-utils/SensorsVtsEnvironmentBase.h" #include <cinttypes> Loading @@ -43,6 +44,9 @@ using aidl::android::hardware::sensors::SensorType; using android::ProcessState; using std::chrono::duration_cast; constexpr size_t kEventSize = static_cast<size_t>(ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH); namespace { static void assertTypeMatchStringType(SensorType type, const std::string& stringType) { Loading Loading @@ -97,6 +101,24 @@ static void assertTypeMatchStringType(SensorType type, const std::string& string } } bool isDirectChannelTypeSupported(SensorInfo sensor, ISensors::SharedMemInfo::SharedMemType type) { switch (type) { case ISensors::SharedMemInfo::SharedMemType::ASHMEM: return (sensor.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM) != 0; case ISensors::SharedMemInfo::SharedMemType::GRALLOC: return (sensor.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC) != 0; default: return false; } } bool isDirectReportRateSupported(SensorInfo sensor, ISensors::RateLevel rate) { unsigned int r = static_cast<unsigned int>(sensor.flags & SensorInfo::SENSOR_FLAG_BITS_MASK_DIRECT_REPORT) >> static_cast<unsigned int>(SensorInfo::SENSOR_FLAG_SHIFT_DIRECT_REPORT); return r >= static_cast<unsigned int>(rate); } int expectedReportModeForType(SensorType type) { switch (type) { case SensorType::ACCELEROMETER: Loading Loading @@ -286,6 +308,24 @@ class SensorsAidlTest : public testing::TestWithParam<std::string> { std::vector<SensorInfo> getOneShotSensors(); std::vector<SensorInfo> getInjectEventSensors(); void verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType memType); void verifyRegisterDirectChannel( std::shared_ptr<SensorsAidlTestSharedMemory<SensorType, Event>> mem, int32_t* directChannelHandle, bool supportsSharedMemType, bool supportsAnyDirectChannel); void verifyConfigure(const SensorInfo& sensor, ISensors::SharedMemInfo::SharedMemType memType, int32_t directChannelHandle, bool directChannelSupported); void queryDirectChannelSupport(ISensors::SharedMemInfo::SharedMemType memType, bool* supportsSharedMemType, bool* supportsAnyDirectChannel); void verifyUnregisterDirectChannel(int32_t* directChannelHandle, bool supportsAnyDirectChannel); void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, ISensors::RateLevel rateLevel, int32_t* reportToken); inline std::shared_ptr<ISensors>& getSensors() { return mEnvironment->mSensors; } inline SensorsAidlEnvironment* getEnvironment() { return mEnvironment; } Loading Loading @@ -313,6 +353,18 @@ class SensorsAidlTest : public testing::TestWithParam<std::string> { ndk::ScopedAStatus flush(int32_t sensorHandle) { return getSensors()->flush(sensorHandle); } ndk::ScopedAStatus registerDirectChannel(const ISensors::SharedMemInfo& mem, int32_t* aidlReturn); ndk::ScopedAStatus unregisterDirectChannel(int32_t* channelHandle) { return getSensors()->unregisterDirectChannel(*channelHandle); } ndk::ScopedAStatus configDirectReport(int32_t sensorHandle, int32_t channelHandle, ISensors::RateLevel rate, int32_t* reportToken) { return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, reportToken); } void runSingleFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor, int32_t expectedFlushCount, bool expectedResult); Loading @@ -334,6 +386,19 @@ class SensorsAidlTest : public testing::TestWithParam<std::string> { SensorsAidlEnvironment* mEnvironment; }; ndk::ScopedAStatus SensorsAidlTest::registerDirectChannel(const ISensors::SharedMemInfo& mem, int32_t* aidlReturn) { // If registeration of a channel succeeds, add the handle of channel to a set so that it can be // unregistered when test fails. Unregister a channel does not remove the handle on purpose. // Unregistering a channel more than once should not have negative effect. ndk::ScopedAStatus status = getSensors()->registerDirectChannel(mem, aidlReturn); if (status.isOk()) { mDirectChannelHandles.insert(*aidlReturn); } return status; } std::vector<SensorInfo> SensorsAidlTest::getSensorsList() { std::vector<SensorInfo> sensorInfoList; checkIsOk(getSensors()->getSensorsList(&sensorInfoList)); Loading Loading @@ -850,12 +915,141 @@ TEST_P(SensorsAidlTest, NoStaleEvents) { } } void SensorsAidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, ISensors::RateLevel rateLevel, int32_t* reportToken) { ndk::ScopedAStatus status = configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel, reportToken); SCOPED_TRACE(::testing::Message() << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name); if (isDirectReportRateSupported(sensor, rateLevel)) { ASSERT_TRUE(status.isOk()); if (rateLevel != ISensors::RateLevel::STOP) { ASSERT_GT(*reportToken, 0); } else { ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT); } } } void SensorsAidlTest::queryDirectChannelSupport(ISensors::SharedMemInfo::SharedMemType memType, bool* supportsSharedMemType, bool* supportsAnyDirectChannel) { *supportsSharedMemType = false; *supportsAnyDirectChannel = false; for (const SensorInfo& curSensor : getSensorsList()) { if (isDirectChannelTypeSupported(curSensor, memType)) { *supportsSharedMemType = true; } if (isDirectChannelTypeSupported(curSensor, ISensors::SharedMemInfo::SharedMemType::ASHMEM) || isDirectChannelTypeSupported(curSensor, ISensors::SharedMemInfo::SharedMemType::GRALLOC)) { *supportsAnyDirectChannel = true; } if (*supportsSharedMemType && *supportsAnyDirectChannel) { break; } } } void SensorsAidlTest::verifyRegisterDirectChannel( std::shared_ptr<SensorsAidlTestSharedMemory<SensorType, Event>> mem, int32_t* directChannelHandle, bool supportsSharedMemType, bool supportsAnyDirectChannel) { char* buffer = mem->getBuffer(); size_t size = mem->getSize(); if (supportsSharedMemType) { memset(buffer, 0xff, size); } int32_t channelHandle; ::ndk::ScopedAStatus status = registerDirectChannel(mem->getSharedMemInfo(), &channelHandle); if (supportsSharedMemType) { ASSERT_TRUE(status.isOk()); ASSERT_EQ(channelHandle, 0); } else { int32_t error = supportsAnyDirectChannel ? EX_ILLEGAL_ARGUMENT : EX_UNSUPPORTED_OPERATION; ASSERT_EQ(status.getExceptionCode(), error); ASSERT_EQ(channelHandle, -1); } directChannelHandle = &channelHandle; } void SensorsAidlTest::verifyUnregisterDirectChannel(int32_t* channelHandle, bool supportsAnyDirectChannel) { int result = supportsAnyDirectChannel ? EX_NONE : EX_UNSUPPORTED_OPERATION; ndk::ScopedAStatus status = unregisterDirectChannel(channelHandle); ASSERT_EQ(status.getExceptionCode(), result); } void SensorsAidlTest::verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType memType) { constexpr size_t kNumEvents = 1; constexpr size_t kMemSize = kNumEvents * kEventSize; std::shared_ptr<SensorsAidlTestSharedMemory<SensorType, Event>> mem( SensorsAidlTestSharedMemory<SensorType, Event>::create(memType, kMemSize)); ASSERT_NE(mem, nullptr); bool supportsSharedMemType; bool supportsAnyDirectChannel; queryDirectChannelSupport(memType, &supportsSharedMemType, &supportsAnyDirectChannel); for (const SensorInfo& sensor : getSensorsList()) { int32_t directChannelHandle = 0; verifyRegisterDirectChannel(mem, &directChannelHandle, supportsSharedMemType, supportsAnyDirectChannel); verifyConfigure(sensor, memType, directChannelHandle, supportsAnyDirectChannel); verifyUnregisterDirectChannel(&directChannelHandle, supportsAnyDirectChannel); } } void SensorsAidlTest::verifyConfigure(const SensorInfo& sensor, ISensors::SharedMemInfo::SharedMemType memType, int32_t directChannelHandle, bool supportsAnyDirectChannel) { SCOPED_TRACE(::testing::Message() << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name); int32_t reportToken = 0; if (isDirectChannelTypeSupported(sensor, memType)) { // Verify that each rate level is properly supported checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::NORMAL, &reportToken); checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::FAST, &reportToken); checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::VERY_FAST, &reportToken); checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::STOP, &reportToken); // Verify that a sensor handle of -1 is only acceptable when using RateLevel::STOP ndk::ScopedAStatus status = configDirectReport(-1 /* sensorHandle */, directChannelHandle, ISensors::RateLevel::NORMAL, &reportToken); ASSERT_EQ(status.getServiceSpecificError(), android::BAD_VALUE); status = configDirectReport(-1 /* sensorHandle */, directChannelHandle, ISensors::RateLevel::STOP, &reportToken); ASSERT_TRUE(status.isOk()); } else { // directChannelHandle will be -1 here, HAL should either reject it as a bad value if there // is some level of direct channel report, otherwise return INVALID_OPERATION if direct // channel is not supported at all int error = supportsAnyDirectChannel ? EX_ILLEGAL_ARGUMENT : EX_UNSUPPORTED_OPERATION; ndk::ScopedAStatus status = configDirectReport(sensor.sensorHandle, directChannelHandle, ISensors::RateLevel::NORMAL, &reportToken); ASSERT_EQ(status.getExceptionCode(), error); } } TEST_P(SensorsAidlTest, DirectChannelAshmem) { // TODO(b/195593357): Implement this verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType::ASHMEM); } TEST_P(SensorsAidlTest, DirectChannelGralloc) { // TODO(b/195593357): Implement this verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType::GRALLOC); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsAidlTest); Loading Loading
sensors/aidl/vts/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ cc_test { shared_libs: [ "libbinder", "libbinder_ndk", "libvndksupport", "libfmq", "android.hardware.common-V2-ndk", "android.hardware.common.fmq-V1-ndk", Loading @@ -41,6 +42,7 @@ cc_test { static_libs: [ "android.hardware.sensors-V1-ndk", "VtsHalSensorsTargetTestUtils", "libaidlcommonsupport", ], test_suites: [ "general-tests", Loading
sensors/aidl/vts/SensorsAidlTestSharedMemory.h 0 → 100644 +218 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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 ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H #define ANDROID_SENSORS_AIDL_TEST_SHARED_MEMORY_H #include "sensors-vts-utils/GrallocWrapper.h" #include <aidlcommonsupport/NativeHandle.h> #include <android-base/macros.h> #include <log/log.h> #include <sys/mman.h> #include <cinttypes> #include <cutils/ashmem.h> using ::aidl::android::hardware::sensors::BnSensors; using ::aidl::android::hardware::sensors::Event; using ::aidl::android::hardware::sensors::ISensors; using ::aidl::android::hardware::sensors::SensorType; template <class SensorType, class Event> class SensorsAidlTestSharedMemory { public: static SensorsAidlTestSharedMemory* create(ISensors::SharedMemInfo::SharedMemType 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 SensorsAidlTestSharedMemory<SensorType, Event>(type, size); if (m->mSize != size || m->mBuffer == nullptr) { delete m; m = nullptr; } return m; } ISensors::SharedMemInfo getSharedMemInfo() const { ISensors::SharedMemInfo mem = { .type = mType, .format = ISensors::SharedMemInfo::SharedMemFormat::SENSORS_EVENT, .size = static_cast<int32_t>(mSize), .memoryHandle = android::dupToAidl(mNativeHandle)}; return mem; } char* getBuffer() const { return mBuffer; } size_t getSize() const { return mSize; } std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const { constexpr size_t kEventSize = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH); constexpr size_t kOffsetSize = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD); constexpr size_t kOffsetToken = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN); constexpr size_t kOffsetType = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE); constexpr size_t kOffsetAtomicCounter = static_cast<size_t>( BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER); constexpr size_t kOffsetTimestamp = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP); constexpr size_t kOffsetData = static_cast<size_t>(BnSensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA); std::vector<Event> events; std::vector<float> data(16); 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; } 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; } int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken); int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType); int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp); ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32 ", timestamp %" PRId64, offset, atomicCounter, token, type, timestamp); Event event = { .timestamp = timestamp, .sensorHandle = token, .sensorType = type, }; event.set<Event::Data>(reinterpret_cast<float*>(mBuffer + offset + kOffsetData)); // event.u.data = android::hardware::hidl_array<float, // 16>(reinterpret_cast<float*>(mBuffer + offset + kOffsetData)); events.push_back(event); lastCounter = atomicCounter; offset += kEventSize; } return events; } virtual ~SensorsAidlTestSharedMemory() { switch (mType) { case ISensors::SharedMemInfo::SharedMemType::ASHMEM: { if (mSize != 0) { ::munmap(mBuffer, mSize); mBuffer = nullptr; ::native_handle_close(mNativeHandle); ::native_handle_delete(mNativeHandle); mNativeHandle = nullptr; mSize = 0; } break; } case ISensors::SharedMemInfo::SharedMemType::GRALLOC: { if (mSize != 0) { mGrallocWrapper->freeBuffer(mNativeHandle); mNativeHandle = nullptr; mSize = 0; } break; } default: { if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) { ALOGE("SensorsAidlTestSharedMemory %p not properly destructed: " "type %d, native handle %p, size %zu, buffer %p", this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer); } break; } } } private: SensorsAidlTestSharedMemory(ISensors::SharedMemInfo::SharedMemType type, size_t size) : mType(type), mSize(0), mBuffer(nullptr) { native_handle_t* handle = nullptr; char* buffer = nullptr; switch (type) { case ISensors::SharedMemInfo::SharedMemType::ASHMEM: { int fd; handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/); if (handle != nullptr) { handle->data[0] = fd = ::ashmem_create_region("SensorsAidlTestSharedMemory", size); if (handle->data[0] > 0) { // memory is pinned by default buffer = static_cast<char*>( ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); if (buffer != reinterpret_cast<char*>(MAP_FAILED)) { break; } ::native_handle_close(handle); } ::native_handle_delete(handle); handle = nullptr; } break; } case ISensors::SharedMemInfo::SharedMemType::GRALLOC: { mGrallocWrapper = std::make_unique<::android::GrallocWrapper>(); if (!mGrallocWrapper->isInitialized()) { break; } std::pair<native_handle_t*, void*> buf = mGrallocWrapper->allocate(size); handle = buf.first; buffer = static_cast<char*>(buf.second); break; } default: break; } if (buffer != nullptr) { mNativeHandle = handle; mSize = size; mBuffer = buffer; } } ISensors::SharedMemInfo::SharedMemType mType; native_handle_t* mNativeHandle; size_t mSize; char* mBuffer; std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper; DISALLOW_COPY_AND_ASSIGN(SensorsAidlTestSharedMemory); }; #endif // ANDROID_SENSORS_TEST_SHARED_MEMORY_H
sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp +196 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <utils/SystemClock.h> #include "SensorsAidlEnvironment.h" #include "SensorsAidlTestSharedMemory.h" #include "sensors-vts-utils/SensorsVtsEnvironmentBase.h" #include <cinttypes> Loading @@ -43,6 +44,9 @@ using aidl::android::hardware::sensors::SensorType; using android::ProcessState; using std::chrono::duration_cast; constexpr size_t kEventSize = static_cast<size_t>(ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH); namespace { static void assertTypeMatchStringType(SensorType type, const std::string& stringType) { Loading Loading @@ -97,6 +101,24 @@ static void assertTypeMatchStringType(SensorType type, const std::string& string } } bool isDirectChannelTypeSupported(SensorInfo sensor, ISensors::SharedMemInfo::SharedMemType type) { switch (type) { case ISensors::SharedMemInfo::SharedMemType::ASHMEM: return (sensor.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM) != 0; case ISensors::SharedMemInfo::SharedMemType::GRALLOC: return (sensor.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC) != 0; default: return false; } } bool isDirectReportRateSupported(SensorInfo sensor, ISensors::RateLevel rate) { unsigned int r = static_cast<unsigned int>(sensor.flags & SensorInfo::SENSOR_FLAG_BITS_MASK_DIRECT_REPORT) >> static_cast<unsigned int>(SensorInfo::SENSOR_FLAG_SHIFT_DIRECT_REPORT); return r >= static_cast<unsigned int>(rate); } int expectedReportModeForType(SensorType type) { switch (type) { case SensorType::ACCELEROMETER: Loading Loading @@ -286,6 +308,24 @@ class SensorsAidlTest : public testing::TestWithParam<std::string> { std::vector<SensorInfo> getOneShotSensors(); std::vector<SensorInfo> getInjectEventSensors(); void verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType memType); void verifyRegisterDirectChannel( std::shared_ptr<SensorsAidlTestSharedMemory<SensorType, Event>> mem, int32_t* directChannelHandle, bool supportsSharedMemType, bool supportsAnyDirectChannel); void verifyConfigure(const SensorInfo& sensor, ISensors::SharedMemInfo::SharedMemType memType, int32_t directChannelHandle, bool directChannelSupported); void queryDirectChannelSupport(ISensors::SharedMemInfo::SharedMemType memType, bool* supportsSharedMemType, bool* supportsAnyDirectChannel); void verifyUnregisterDirectChannel(int32_t* directChannelHandle, bool supportsAnyDirectChannel); void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, ISensors::RateLevel rateLevel, int32_t* reportToken); inline std::shared_ptr<ISensors>& getSensors() { return mEnvironment->mSensors; } inline SensorsAidlEnvironment* getEnvironment() { return mEnvironment; } Loading Loading @@ -313,6 +353,18 @@ class SensorsAidlTest : public testing::TestWithParam<std::string> { ndk::ScopedAStatus flush(int32_t sensorHandle) { return getSensors()->flush(sensorHandle); } ndk::ScopedAStatus registerDirectChannel(const ISensors::SharedMemInfo& mem, int32_t* aidlReturn); ndk::ScopedAStatus unregisterDirectChannel(int32_t* channelHandle) { return getSensors()->unregisterDirectChannel(*channelHandle); } ndk::ScopedAStatus configDirectReport(int32_t sensorHandle, int32_t channelHandle, ISensors::RateLevel rate, int32_t* reportToken) { return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, reportToken); } void runSingleFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor, int32_t expectedFlushCount, bool expectedResult); Loading @@ -334,6 +386,19 @@ class SensorsAidlTest : public testing::TestWithParam<std::string> { SensorsAidlEnvironment* mEnvironment; }; ndk::ScopedAStatus SensorsAidlTest::registerDirectChannel(const ISensors::SharedMemInfo& mem, int32_t* aidlReturn) { // If registeration of a channel succeeds, add the handle of channel to a set so that it can be // unregistered when test fails. Unregister a channel does not remove the handle on purpose. // Unregistering a channel more than once should not have negative effect. ndk::ScopedAStatus status = getSensors()->registerDirectChannel(mem, aidlReturn); if (status.isOk()) { mDirectChannelHandles.insert(*aidlReturn); } return status; } std::vector<SensorInfo> SensorsAidlTest::getSensorsList() { std::vector<SensorInfo> sensorInfoList; checkIsOk(getSensors()->getSensorsList(&sensorInfoList)); Loading Loading @@ -850,12 +915,141 @@ TEST_P(SensorsAidlTest, NoStaleEvents) { } } void SensorsAidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, ISensors::RateLevel rateLevel, int32_t* reportToken) { ndk::ScopedAStatus status = configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel, reportToken); SCOPED_TRACE(::testing::Message() << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name); if (isDirectReportRateSupported(sensor, rateLevel)) { ASSERT_TRUE(status.isOk()); if (rateLevel != ISensors::RateLevel::STOP) { ASSERT_GT(*reportToken, 0); } else { ASSERT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT); } } } void SensorsAidlTest::queryDirectChannelSupport(ISensors::SharedMemInfo::SharedMemType memType, bool* supportsSharedMemType, bool* supportsAnyDirectChannel) { *supportsSharedMemType = false; *supportsAnyDirectChannel = false; for (const SensorInfo& curSensor : getSensorsList()) { if (isDirectChannelTypeSupported(curSensor, memType)) { *supportsSharedMemType = true; } if (isDirectChannelTypeSupported(curSensor, ISensors::SharedMemInfo::SharedMemType::ASHMEM) || isDirectChannelTypeSupported(curSensor, ISensors::SharedMemInfo::SharedMemType::GRALLOC)) { *supportsAnyDirectChannel = true; } if (*supportsSharedMemType && *supportsAnyDirectChannel) { break; } } } void SensorsAidlTest::verifyRegisterDirectChannel( std::shared_ptr<SensorsAidlTestSharedMemory<SensorType, Event>> mem, int32_t* directChannelHandle, bool supportsSharedMemType, bool supportsAnyDirectChannel) { char* buffer = mem->getBuffer(); size_t size = mem->getSize(); if (supportsSharedMemType) { memset(buffer, 0xff, size); } int32_t channelHandle; ::ndk::ScopedAStatus status = registerDirectChannel(mem->getSharedMemInfo(), &channelHandle); if (supportsSharedMemType) { ASSERT_TRUE(status.isOk()); ASSERT_EQ(channelHandle, 0); } else { int32_t error = supportsAnyDirectChannel ? EX_ILLEGAL_ARGUMENT : EX_UNSUPPORTED_OPERATION; ASSERT_EQ(status.getExceptionCode(), error); ASSERT_EQ(channelHandle, -1); } directChannelHandle = &channelHandle; } void SensorsAidlTest::verifyUnregisterDirectChannel(int32_t* channelHandle, bool supportsAnyDirectChannel) { int result = supportsAnyDirectChannel ? EX_NONE : EX_UNSUPPORTED_OPERATION; ndk::ScopedAStatus status = unregisterDirectChannel(channelHandle); ASSERT_EQ(status.getExceptionCode(), result); } void SensorsAidlTest::verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType memType) { constexpr size_t kNumEvents = 1; constexpr size_t kMemSize = kNumEvents * kEventSize; std::shared_ptr<SensorsAidlTestSharedMemory<SensorType, Event>> mem( SensorsAidlTestSharedMemory<SensorType, Event>::create(memType, kMemSize)); ASSERT_NE(mem, nullptr); bool supportsSharedMemType; bool supportsAnyDirectChannel; queryDirectChannelSupport(memType, &supportsSharedMemType, &supportsAnyDirectChannel); for (const SensorInfo& sensor : getSensorsList()) { int32_t directChannelHandle = 0; verifyRegisterDirectChannel(mem, &directChannelHandle, supportsSharedMemType, supportsAnyDirectChannel); verifyConfigure(sensor, memType, directChannelHandle, supportsAnyDirectChannel); verifyUnregisterDirectChannel(&directChannelHandle, supportsAnyDirectChannel); } } void SensorsAidlTest::verifyConfigure(const SensorInfo& sensor, ISensors::SharedMemInfo::SharedMemType memType, int32_t directChannelHandle, bool supportsAnyDirectChannel) { SCOPED_TRACE(::testing::Message() << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name); int32_t reportToken = 0; if (isDirectChannelTypeSupported(sensor, memType)) { // Verify that each rate level is properly supported checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::NORMAL, &reportToken); checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::FAST, &reportToken); checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::VERY_FAST, &reportToken); checkRateLevel(sensor, directChannelHandle, ISensors::RateLevel::STOP, &reportToken); // Verify that a sensor handle of -1 is only acceptable when using RateLevel::STOP ndk::ScopedAStatus status = configDirectReport(-1 /* sensorHandle */, directChannelHandle, ISensors::RateLevel::NORMAL, &reportToken); ASSERT_EQ(status.getServiceSpecificError(), android::BAD_VALUE); status = configDirectReport(-1 /* sensorHandle */, directChannelHandle, ISensors::RateLevel::STOP, &reportToken); ASSERT_TRUE(status.isOk()); } else { // directChannelHandle will be -1 here, HAL should either reject it as a bad value if there // is some level of direct channel report, otherwise return INVALID_OPERATION if direct // channel is not supported at all int error = supportsAnyDirectChannel ? EX_ILLEGAL_ARGUMENT : EX_UNSUPPORTED_OPERATION; ndk::ScopedAStatus status = configDirectReport(sensor.sensorHandle, directChannelHandle, ISensors::RateLevel::NORMAL, &reportToken); ASSERT_EQ(status.getExceptionCode(), error); } } TEST_P(SensorsAidlTest, DirectChannelAshmem) { // TODO(b/195593357): Implement this verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType::ASHMEM); } TEST_P(SensorsAidlTest, DirectChannelGralloc) { // TODO(b/195593357): Implement this verifyDirectChannel(ISensors::SharedMemInfo::SharedMemType::GRALLOC); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsAidlTest); Loading