diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp index 9b8e3d444b..8e8413c6a2 100644 --- a/sensors/2.0/vts/functional/Android.bp +++ b/sensors/2.0/vts/functional/Android.bp @@ -26,6 +26,7 @@ cc_test { "android.hardware.graphics.mapper@2.0", "android.hardware.sensors@1.0", "android.hardware.sensors@2.0", + "libfmq", "VtsHalSensorsTargetTestUtils", ], } diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp index 20d0838b1a..54442876f4 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp @@ -16,44 +16,65 @@ #include "SensorsHidlEnvironmentV2_0.h" +#include #include +#include #include +using ::android::hardware::EventFlag; using ::android::hardware::hidl_vec; using ::android::hardware::sensors::V1_0::Result; using ::android::hardware::sensors::V1_0::SensorInfo; +using ::android::hardware::sensors::V2_0::EventQueueFlagBits; using ::android::hardware::sensors::V2_0::ISensors; +template +constexpr typename std::underlying_type::type asBaseType(EnumType value) { + return static_cast::type>(value); +} + +constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT; + bool SensorsHidlEnvironmentV2_0::resetHal() { - std::string step; bool succeed = false; do { - step = "getService()"; - sensors = ISensors::getService( + mSensors = ISensors::getService( SensorsHidlEnvironmentV2_0::Instance()->getServiceName()); - if (sensors == nullptr) { + if (mSensors == nullptr) { break; } - step = "getSensorList"; + // Initialize FMQs + mEventQueue = std::make_unique(MAX_RECEIVE_BUFFER_EVENT_COUNT, + true /* configureEventFlagWord */); + + mWakeLockQueue = std::make_unique(MAX_RECEIVE_BUFFER_EVENT_COUNT, + true /* configureEventFlagWord */); + + if (mEventQueue == nullptr || mWakeLockQueue == nullptr) { + break; + } + + EventFlag::deleteEventFlag(&mEventQueueFlag); + EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag); + if (mEventQueueFlag == nullptr) { + break; + } + + mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(), + nullptr /* TODO: callback */); + std::vector sensorList; - if (!sensors - ->getSensorsList([&](const hidl_vec& list) { - sensorList.reserve(list.size()); - for (size_t i = 0; i < list.size(); ++i) { - sensorList.push_back(list[i]); - } - }) + if (!mSensors->getSensorsList([&](const hidl_vec& list) { sensorList = list; }) .isOk()) { break; } // stop each sensor individually - step = "stop each sensor"; bool ok = true; for (const auto& i : sensorList) { - if (!sensors->activate(i.sensorHandle, false).isOk()) { + if (!mSensors->activate(i.sensorHandle, false).isOk()) { ok = false; break; } @@ -63,31 +84,58 @@ bool SensorsHidlEnvironmentV2_0::resetHal() { } // mark it done - step = "done"; succeed = true; } while (0); - if (succeed) { - return true; + if (!succeed) { + mSensors = nullptr; } - sensors = nullptr; - return false; + return succeed; +} + +void SensorsHidlEnvironmentV2_0::HidlTearDown() { + stopThread = true; + + // Wake up the event queue so the poll thread can exit + mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS)); + pollThread.join(); + + EventFlag::deleteEventFlag(&mEventQueueFlag); } void SensorsHidlEnvironmentV2_0::startPollingThread() { stopThread = false; - pollThread = std::thread(pollingThread, this, std::ref(stopThread)); - events.reserve(128); + pollThread = std::thread(pollingThread, this); + events.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT); } -void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* /*env*/, - std::atomic_bool& stop) { +void SensorsHidlEnvironmentV2_0::readEvents() { + size_t availableEvents = mEventQueue->availableToRead(); + + if (availableEvents == 0) { + uint32_t eventFlagState = 0; + + mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS), &eventFlagState); + availableEvents = mEventQueue->availableToRead(); + } + + size_t eventsToRead = std::min(availableEvents, mEventBuffer.size()); + if (eventsToRead > 0) { + if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) { + for (const auto& e : mEventBuffer) { + addEvent(e); + } + } + } +} + +void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* env) { ALOGD("polling thread start"); - while (!stop) { - // TODO: implement reading event queue - stop = true; + while (!env->stopThread.load()) { + env->readEvents(); } + ALOGD("polling thread end"); } diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h index 43ddd238ed..724192376f 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h @@ -21,12 +21,15 @@ #include #include +#include #include +#include #include #include using ::android::sp; +using ::android::hardware::MessageQueue; class SensorsHidlTest; class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { @@ -42,18 +45,81 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { registerTestService(); } + virtual void HidlTearDown() override; + private: friend SensorsHidlTest; - // sensors hidl service - sp sensors; - SensorsHidlEnvironmentV2_0() {} + SensorsHidlEnvironmentV2_0() : mEventQueueFlag(nullptr) {} + /** + * Resets the HAL with new FMQs and a new Event Flag + * + * @return bool true if successful, false otherwise + */ bool resetHal() override; + + /** + * Starts the polling thread that reads sensor events from the Event FMQ + */ void startPollingThread() override; - static void pollingThread(SensorsHidlEnvironmentV2_0* env, std::atomic_bool& stop); + + /** + * Thread responsible for calling functions to read Event FMQ + * + * @param env SensorEnvironment to being polling for events on + */ + static void pollingThread(SensorsHidlEnvironmentV2_0* env); + + /** + * Reads and saves sensor events from the Event FMQ + */ + void readEvents(); GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_0); + + /** + * Pointer to the Sensors HAL Interface that allows the test to call HAL functions. + */ + sp mSensors; + + /** + * Type used to simplify the creation of the Event FMQ + */ + typedef MessageQueue EventMessageQueue; + + /** + * Type used to simplify the creation of the Wake Lock FMQ + */ + typedef MessageQueue WakeLockQueue; + + /** + * The Event FMQ where the test framework is able to read sensor events that the Sensors HAL + * has written. + */ + std::unique_ptr mEventQueue; + + /** + * The Wake Lock FMQ is used by the test to notify the Sensors HAL whenever it has processed + * WAKE_UP sensor events. + */ + std::unique_ptr mWakeLockQueue; + + /** + * The Event Queue Flag notifies the test framework when sensor events have been written to the + * Event FMQ by the Sensors HAL. + */ + ::android::hardware::EventFlag* mEventQueueFlag; + + /** + * The maximum number of sensor events that can be read from the Event FMQ at one time. + */ + static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 128; + + /** + * An array that is used to store sensor events read from the Event FMQ + */ + std::array mEventBuffer; }; #endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 204d7b2007..7c6f01065c 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -42,36 +42,38 @@ class SensorsHidlTest : public SensorsHidlTestBase { std::vector getSensorsList(); // implementation wrapper Return getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override { - return S()->getSensorsList(_hidl_cb); + return getSensors()->getSensorsList(_hidl_cb); } Return activate(int32_t sensorHandle, bool enabled) override; Return batch(int32_t sensorHandle, int64_t samplingPeriodNs, int64_t maxReportLatencyNs) override { - return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); + return getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); } - Return flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); } + Return flush(int32_t sensorHandle) override { + return getSensors()->flush(sensorHandle); + } Return injectSensorData(const Event& event) override { - return S()->injectSensorData(event); + return getSensors()->injectSensorData(event); } Return registerDirectChannel(const SharedMemInfo& mem, ISensors::registerDirectChannel_cb _hidl_cb) override; Return unregisterDirectChannel(int32_t channelHandle) override { - return S()->unregisterDirectChannel(channelHandle); + return getSensors()->unregisterDirectChannel(channelHandle); } Return configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, ISensors::configDirectReport_cb _hidl_cb) override { - return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); + return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); } - inline sp<::android::hardware::sensors::V2_0::ISensors>& S() { - return SensorsHidlEnvironmentV2_0::Instance()->sensors; + inline sp<::android::hardware::sensors::V2_0::ISensors>& getSensors() { + return SensorsHidlEnvironmentV2_0::Instance()->mSensors; } SensorsHidlEnvironmentBase* getEnvironment() override { @@ -87,7 +89,7 @@ Return SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) { if (enabled) { mSensorHandles.insert(sensorHandle); } - return S()->activate(sensorHandle, enabled); + return getSensors()->activate(sensorHandle, enabled); } Return SensorsHidlTest::registerDirectChannel(const SharedMemInfo& mem, @@ -95,7 +97,7 @@ Return SensorsHidlTest::registerDirectChannel(const SharedMemInfo& mem, // 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. - S()->registerDirectChannel(mem, [&](auto result, auto channelHandle) { + getSensors()->registerDirectChannel(mem, [&](auto result, auto channelHandle) { if (result == Result::OK) { mDirectChannelHandles.insert(channelHandle); } @@ -108,7 +110,7 @@ SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) { SensorInfo ret; ret.type = (SensorType)-1; - S()->getSensorsList([&](const auto& list) { + getSensors()->getSensorsList([&](const auto& list) { const size_t count = list.size(); for (size_t i = 0; i < count; ++i) { if (list[i].type == type) { @@ -124,7 +126,7 @@ SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) { std::vector SensorsHidlTest::getSensorsList() { std::vector ret; - S()->getSensorsList([&](const auto& list) { + getSensors()->getSensorsList([&](const auto& list) { const size_t count = list.size(); ret.reserve(list.size()); for (size_t i = 0; i < count; ++i) { @@ -137,7 +139,7 @@ std::vector SensorsHidlTest::getSensorsList() { // Test if sensor list returned is valid TEST_F(SensorsHidlTest, SensorListValid) { - S()->getSensorsList([&](const auto& list) { + getSensors()->getSensorsList([&](const auto& list) { const size_t count = list.size(); for (size_t i = 0; i < count; ++i) { const auto& s = list[i]; @@ -191,9 +193,9 @@ TEST_F(SensorsHidlTest, SetOperationMode) { return; } - ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL)); - ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::DATA_INJECTION)); - ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL)); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION)); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); } // Test if sensor list returned is valid @@ -213,8 +215,8 @@ TEST_F(SensorsHidlTest, InjectSensorEventData) { return; } - ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL)); - ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::DATA_INJECTION)); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION)); for (const auto& s : sensorSupportInjection) { switch (s.type) { @@ -230,14 +232,14 @@ TEST_F(SensorsHidlTest, InjectSensorEventData) { Vec3 v = {1, 2, 3, SensorStatus::ACCURACY_HIGH}; dummy.u.vec3 = v; - EXPECT_EQ(Result::OK, S()->injectSensorData(dummy)); + EXPECT_EQ(Result::OK, getSensors()->injectSensorData(dummy)); break; } default: break; } } - ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL)); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); } // Test if sensor hal can do UI speed accelerometer streaming properly diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h index 4a6f713824..96e6085356 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h @@ -30,8 +30,8 @@ class SensorsHidlEnvironmentBase : public ::testing::VtsHalHidlTargetTestEnvBase { public: using Event = ::android::hardware::sensors::V1_0::Event; - void HidlSetUp() override; - void HidlTearDown() override; + virtual void HidlSetUp() override; + virtual void HidlTearDown() override; // Get and clear all events collected so far (like "cat" shell command). // If output is nullptr, it clears all collected events.