From a9a5eb411ea8f41d7e929ca1ddc46d762ce1e81b Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Wed, 5 Feb 2020 19:49:59 -0500 Subject: [PATCH] Add VTS tests for Sensors HAL 2.1 Bug: 144139857 Test: atest VtsHalSensorsV2_0TargetTest VtsHalSensorsV2_1TargetTest Change-Id: If2b751929b8d89c9d381032f5e8424a24719b6bd --- .../compatibility_matrix.current.xml | 2 +- sensors/1.0/vts/functional/Android.bp | 8 +- .../functional/SensorsHidlEnvironmentV1_0.h | 5 +- .../VtsHalSensorsV1_0TargetTest.cpp | 59 +- sensors/2.0/vts/functional/Android.bp | 14 +- .../VtsHalSensorsV2_0TargetTest.cpp | 1119 +--------------- sensors/2.1/vts/functional/Android.bp | 48 + sensors/2.1/vts/functional/AndroidTest.xml | 39 + sensors/2.1/vts/functional/OWNERS | 8 + .../VtsHalSensorsV2_1TargetTest.cpp | 22 + sensors/common/vts/2_X/Android.bp | 44 + .../vts/2_X/SensorsHidlEnvironmentV2_X.cpp} | 54 +- .../vts/2_X/SensorsHidlEnvironmentV2_X.h} | 51 +- .../vts/2_X/VtsHalSensorsV2_XTargetTest.h | 1186 +++++++++++++++++ sensors/common/vts/utils/Android.bp | 8 +- .../vts/utils/SensorsHidlEnvironmentBase.cpp | 69 - .../common/vts/utils/SensorsHidlTestBase.cpp | 584 -------- .../vts/utils/SensorsTestSharedMemory.cpp | 189 --- .../sensors-vts-utils/SensorEventsChecker.h | 35 +- .../SensorsHidlEnvironmentBase.h | 66 +- .../sensors-vts-utils/SensorsHidlTestBase.h | 608 ++++++++- .../SensorsTestSharedMemory.h | 178 ++- 22 files changed, 2255 insertions(+), 2141 deletions(-) create mode 100644 sensors/2.1/vts/functional/Android.bp create mode 100644 sensors/2.1/vts/functional/AndroidTest.xml create mode 100644 sensors/2.1/vts/functional/OWNERS create mode 100644 sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp create mode 100644 sensors/common/vts/2_X/Android.bp rename sensors/{2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp => common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp} (70%) rename sensors/{2.0/vts/functional/SensorsHidlEnvironmentV2_0.h => common/vts/2_X/SensorsHidlEnvironmentV2_X.h} (68%) create mode 100644 sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h delete mode 100644 sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp delete mode 100644 sensors/common/vts/utils/SensorsHidlTestBase.cpp delete mode 100644 sensors/common/vts/utils/SensorsTestSharedMemory.cpp diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index f8cec640cc..c5466c91ac 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -416,7 +416,7 @@ android.hardware.sensors 1.0 - 2.0 + 2.0-1 ISensors default diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp index 1167fd4e0c..aaefccbe19 100644 --- a/sensors/1.0/vts/functional/Android.bp +++ b/sensors/1.0/vts/functional/Android.bp @@ -20,7 +20,7 @@ cc_test { defaults: ["VtsHalTargetTestDefaults"], srcs: [ "SensorsHidlEnvironmentV1_0.cpp", - "VtsHalSensorsV1_0TargetTest.cpp" + "VtsHalSensorsV1_0TargetTest.cpp", ], static_libs: [ "android.hardware.graphics.allocator@2.0", @@ -31,6 +31,8 @@ cc_test { "android.hardware.sensors@1.0", "VtsHalSensorsTargetTestUtils", ], - test_suites: ["general-tests", "vts-core"], + test_suites: [ + "general-tests", + "vts-core", + ], } - diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h index 29bfa507d9..485ed1ed87 100644 --- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h +++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h @@ -29,8 +29,9 @@ using ::android::sp; class SensorsHidlTest; -class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase { - public: +class SensorsHidlEnvironmentV1_0 + : public SensorsHidlEnvironmentBase<::android::hardware::sensors::V1_0::Event> { + public: using Event = ::android::hardware::sensors::V1_0::Event; SensorsHidlEnvironmentV1_0(const std::string& service_name) : SensorsHidlEnvironmentBase(service_name) {} diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp index 2cad54d1ba..e298651419 100644 --- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp +++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp @@ -33,8 +33,7 @@ using ::android::sp; using namespace ::android::hardware::sensors::V1_0; // The main test class for SENSORS HIDL HAL. - -class SensorsHidlTest : public SensorsHidlTestBase { +class SensorsHidlTest : public SensorsHidlTestBase { public: virtual void SetUp() override { mEnvironment = new SensorsHidlEnvironmentV1_0(GetParam()); @@ -80,7 +79,7 @@ class SensorsHidlTest : public SensorsHidlTestBase { inline sp& S() { return mEnvironment->sensors; } - SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; } + SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; } private: // Test environment for sensors HAL. @@ -257,55 +256,55 @@ TEST_P(SensorsHidlTest, InjectSensorEventData) { // Test if sensor hal can do UI speed accelerometer streaming properly TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) { testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200), - std::chrono::seconds(5), sAccelNormChecker); + std::chrono::seconds(5), mAccelNormChecker); } // Test if sensor hal can do normal speed accelerometer streaming properly TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) { testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20), - std::chrono::seconds(5), sAccelNormChecker); + std::chrono::seconds(5), mAccelNormChecker); } // Test if sensor hal can do game speed accelerometer streaming properly TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) { testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5), - std::chrono::seconds(5), sAccelNormChecker); + std::chrono::seconds(5), mAccelNormChecker); } // Test if sensor hal can do UI speed gyroscope streaming properly TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) { testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200), - std::chrono::seconds(5), sGyroNormChecker); + std::chrono::seconds(5), mGyroNormChecker); } // Test if sensor hal can do normal speed gyroscope streaming properly TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) { testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20), - std::chrono::seconds(5), sGyroNormChecker); + std::chrono::seconds(5), mGyroNormChecker); } // Test if sensor hal can do game speed gyroscope streaming properly TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) { testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5), - std::chrono::seconds(5), sGyroNormChecker); + std::chrono::seconds(5), mGyroNormChecker); } // Test if sensor hal can do UI speed magnetometer streaming properly TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) { testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200), - std::chrono::seconds(5), NullChecker()); + std::chrono::seconds(5), NullChecker()); } // Test if sensor hal can do normal speed magnetometer streaming properly TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) { testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20), - std::chrono::seconds(5), NullChecker()); + std::chrono::seconds(5), NullChecker()); } // Test if sensor hal can do game speed magnetometer streaming properly TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) { testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5), - std::chrono::seconds(5), NullChecker()); + std::chrono::seconds(5), NullChecker()); } // Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active @@ -344,109 +343,109 @@ TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) { // Test sensor event direct report with ashmem for accel sensor at normal rate TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL, - sAccelNormChecker); + mAccelNormChecker); } // Test sensor event direct report with ashmem for accel sensor at fast rate TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST, - sAccelNormChecker); + mAccelNormChecker); } // Test sensor event direct report with ashmem for accel sensor at very fast rate TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, - RateLevel::VERY_FAST, sAccelNormChecker); + RateLevel::VERY_FAST, mAccelNormChecker); } // Test sensor event direct report with ashmem for gyro sensor at normal rate TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) { testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL, - sGyroNormChecker); + mGyroNormChecker); } // Test sensor event direct report with ashmem for gyro sensor at fast rate TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) { testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST, - sGyroNormChecker); + mGyroNormChecker); } // Test sensor event direct report with ashmem for gyro sensor at very fast rate TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) { testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST, - sGyroNormChecker); + mGyroNormChecker); } // Test sensor event direct report with ashmem for mag sensor at normal rate TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) { testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL, - NullChecker()); + NullChecker()); } // Test sensor event direct report with ashmem for mag sensor at fast rate TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) { testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST, - NullChecker()); + NullChecker()); } // Test sensor event direct report with ashmem for mag sensor at very fast rate TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) { testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, - RateLevel::VERY_FAST, NullChecker()); + RateLevel::VERY_FAST, NullChecker()); } // Test sensor event direct report with gralloc for accel sensor at normal rate TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL, - sAccelNormChecker); + mAccelNormChecker); } // Test sensor event direct report with gralloc for accel sensor at fast rate TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST, - sAccelNormChecker); + mAccelNormChecker); } // Test sensor event direct report with gralloc for accel sensor at very fast rate TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, - RateLevel::VERY_FAST, sAccelNormChecker); + RateLevel::VERY_FAST, mAccelNormChecker); } // Test sensor event direct report with gralloc for gyro sensor at normal rate TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) { testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL, - sGyroNormChecker); + mGyroNormChecker); } // Test sensor event direct report with gralloc for gyro sensor at fast rate TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) { testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST, - sGyroNormChecker); + mGyroNormChecker); } // Test sensor event direct report with gralloc for gyro sensor at very fast rate TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) { testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST, - sGyroNormChecker); + mGyroNormChecker); } // Test sensor event direct report with gralloc for mag sensor at normal rate TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) { testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL, - NullChecker()); + NullChecker()); } // Test sensor event direct report with gralloc for mag sensor at fast rate TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) { testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST, - NullChecker()); + NullChecker()); } // Test sensor event direct report with gralloc for mag sensor at very fast rate TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) { testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, - RateLevel::VERY_FAST, NullChecker()); + RateLevel::VERY_FAST, NullChecker()); } INSTANTIATE_TEST_SUITE_P( diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp index 4765fa2797..22a5091a67 100644 --- a/sensors/2.0/vts/functional/Android.bp +++ b/sensors/2.0/vts/functional/Android.bp @@ -19,8 +19,10 @@ cc_test { cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""], defaults: ["VtsHalTargetTestDefaults"], srcs: [ - "SensorsHidlEnvironmentV2_0.cpp", - "VtsHalSensorsV2_0TargetTest.cpp" + "VtsHalSensorsV2_0TargetTest.cpp", + ], + header_libs: [ + "android.hardware.sensors@2.X-shared-utils", ], static_libs: [ "android.hardware.graphics.allocator@2.0", @@ -29,9 +31,15 @@ cc_test { "android.hardware.graphics.mapper@2.1", "android.hardware.graphics.mapper@3.0", "android.hardware.sensors@1.0", + "android.hardware.sensors@1.0-convert", "android.hardware.sensors@2.0", + "android.hardware.sensors@2.1", "libfmq", "VtsHalSensorsTargetTestUtils", + "VtsHalSensorsV2_XTargetTest", + ], + test_suites: [ + "general-tests", + "vts-core", ], } - diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 540529d8eb..889535005e 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -14,1130 +14,19 @@ * limitations under the License. */ -#include "SensorsHidlEnvironmentV2_0.h" -#include "sensors-vts-utils/SensorsHidlTestBase.h" -#include "sensors-vts-utils/SensorsTestSharedMemory.h" +#include "VtsHalSensorsV2_XTargetTest.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using ::android::sp; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::hardware::sensors::V1_0::MetaDataEventType; -using ::android::hardware::sensors::V1_0::OperationMode; -using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset; -using ::android::hardware::sensors::V1_0::SensorStatus; -using ::android::hardware::sensors::V1_0::SharedMemType; -using ::android::hardware::sensors::V1_0::Vec3; -using std::chrono::duration_cast; -using std::chrono::microseconds; -using std::chrono::milliseconds; -using std::chrono::nanoseconds; - -constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); - -class EventCallback : public IEventCallback { - public: - void reset() { - mFlushMap.clear(); - mEventMap.clear(); - } - - void onEvent(const ::android::hardware::sensors::V1_0::Event& event) override { - if (event.sensorType == SensorType::META_DATA && - event.u.meta.what == MetaDataEventType::META_DATA_FLUSH_COMPLETE) { - std::unique_lock lock(mFlushMutex); - mFlushMap[event.sensorHandle]++; - mFlushCV.notify_all(); - } else if (event.sensorType != SensorType::ADDITIONAL_INFO) { - std::unique_lock lock(mEventMutex); - mEventMap[event.sensorHandle].push_back(event); - mEventCV.notify_all(); - } - } - - int32_t getFlushCount(int32_t sensorHandle) { - std::unique_lock lock(mFlushMutex); - return mFlushMap[sensorHandle]; - } - - void waitForFlushEvents(const std::vector& sensorsToWaitFor, - int32_t numCallsToFlush, milliseconds timeout) { - std::unique_lock lock(mFlushMutex); - mFlushCV.wait_for(lock, timeout, - [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); }); - } - - const std::vector getEvents(int32_t sensorHandle) { - std::unique_lock lock(mEventMutex); - return mEventMap[sensorHandle]; - } - - void waitForEvents(const std::vector& sensorsToWaitFor, milliseconds timeout) { - std::unique_lock lock(mEventMutex); - mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); }); - } - - protected: - bool flushesReceived(const std::vector& sensorsToWaitFor, int32_t numCallsToFlush) { - for (const SensorInfo& sensor : sensorsToWaitFor) { - if (getFlushCount(sensor.sensorHandle) < numCallsToFlush) { - return false; - } - } - return true; - } - - bool eventsReceived(const std::vector& sensorsToWaitFor) { - for (const SensorInfo& sensor : sensorsToWaitFor) { - if (getEvents(sensor.sensorHandle).size() == 0) { - return false; - } - } - return true; - } - - std::map mFlushMap; - std::recursive_mutex mFlushMutex; - std::condition_variable_any mFlushCV; - - std::map> mEventMap; - std::recursive_mutex mEventMutex; - std::condition_variable_any mEventCV; -}; - -// The main test class for SENSORS HIDL HAL. - -class SensorsHidlTest : public SensorsHidlTestBase { - public: - virtual void SetUp() override { - mEnvironment = new SensorsHidlEnvironmentV2_0(GetParam()); - mEnvironment->HidlSetUp(); - // Ensure that we have a valid environment before performing tests - ASSERT_NE(getSensors(), nullptr); - } - - virtual void TearDown() override { mEnvironment->HidlTearDown(); } - - protected: - SensorInfo defaultSensorByType(SensorType type) override; - std::vector getSensorsList(); - // implementation wrapper - Return getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override { - 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 getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); - } - - Return flush(int32_t sensorHandle) override { - return getSensors()->flush(sensorHandle); - } - - Return injectSensorData(const Event& event) override { - return getSensors()->injectSensorData(event); - } - - Return registerDirectChannel(const SharedMemInfo& mem, - ISensors::registerDirectChannel_cb _hidl_cb) override; - - Return unregisterDirectChannel(int32_t channelHandle) override { - return getSensors()->unregisterDirectChannel(channelHandle); - } - - Return configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, - ISensors::configDirectReport_cb _hidl_cb) override { - return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); - } - - inline sp<::android::hardware::sensors::V2_0::ISensors>& getSensors() { - return mEnvironment->mSensors; - } - - SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; } - - // Test helpers - void runSingleFlushTest(const std::vector& sensors, bool activateSensor, - int32_t expectedFlushCount, Result expectedResponse); - void runFlushTest(const std::vector& sensors, bool activateSensor, - int32_t flushCalls, int32_t expectedFlushCount, Result expectedResponse); - - // Helper functions - void activateAllSensors(bool enable); - std::vector getNonOneShotSensors(); - std::vector getNonOneShotAndNonSpecialSensors(); - std::vector getOneShotSensors(); - std::vector getInjectEventSensors(); - int32_t getInvalidSensorHandle(); - bool getDirectChannelSensor(SensorInfo* sensor, SharedMemType* memType, RateLevel* rate); - void verifyDirectChannel(SharedMemType memType); - void verifyRegisterDirectChannel(std::shared_ptr mem, - int32_t* directChannelHandle, bool supportsSharedMemType, - bool supportsAnyDirectChannel); - void verifyConfigure(const SensorInfo& sensor, SharedMemType memType, - int32_t directChannelHandle, bool directChannelSupported); - void verifyUnregisterDirectChannel(int32_t directChannelHandle, bool directChannelSupported); - void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, RateLevel rateLevel); - void queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType, - bool* supportsAnyDirectChannel); - - private: - // Test environment for sensors HAL. - SensorsHidlEnvironmentV2_0* mEnvironment; -}; - -Return SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) { - // If activating a sensor, add the handle in a set so that when test fails it can be turned off. - // The handle is not removed when it is deactivating on purpose so that it is not necessary to - // check the return value of deactivation. Deactivating a sensor more than once does not have - // negative effect. - if (enabled) { - mSensorHandles.insert(sensorHandle); - } - return getSensors()->activate(sensorHandle, enabled); -} - -Return SensorsHidlTest::registerDirectChannel(const SharedMemInfo& mem, - ISensors::registerDirectChannel_cb cb) { - // 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. - getSensors()->registerDirectChannel(mem, [&](auto result, auto channelHandle) { - if (result == Result::OK) { - mDirectChannelHandles.insert(channelHandle); - } - cb(result, channelHandle); - }); - return Void(); -} - -SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) { - SensorInfo ret; - - ret.type = (SensorType)-1; - getSensors()->getSensorsList([&](const auto& list) { - const size_t count = list.size(); - for (size_t i = 0; i < count; ++i) { - if (list[i].type == type) { - ret = list[i]; - return; - } - } - }); - - return ret; -} - -std::vector SensorsHidlTest::getSensorsList() { - std::vector ret; - - getSensors()->getSensorsList([&](const auto& list) { - const size_t count = list.size(); - ret.reserve(list.size()); - for (size_t i = 0; i < count; ++i) { - ret.push_back(list[i]); - } - }); - - return ret; -} - -std::vector SensorsHidlTest::getNonOneShotSensors() { - std::vector sensors; - for (const SensorInfo& info : getSensorsList()) { - if (extractReportMode(info.flags) != SensorFlagBits::ONE_SHOT_MODE) { - sensors.push_back(info); - } - } - return sensors; -} - -std::vector SensorsHidlTest::getNonOneShotAndNonSpecialSensors() { - std::vector sensors; - for (const SensorInfo& info : getSensorsList()) { - SensorFlagBits reportMode = extractReportMode(info.flags); - if (reportMode != SensorFlagBits::ONE_SHOT_MODE && - reportMode != SensorFlagBits::SPECIAL_REPORTING_MODE) { - sensors.push_back(info); - } - } - return sensors; -} - -std::vector SensorsHidlTest::getOneShotSensors() { - std::vector sensors; - for (const SensorInfo& info : getSensorsList()) { - if (extractReportMode(info.flags) == SensorFlagBits::ONE_SHOT_MODE) { - sensors.push_back(info); - } - } - return sensors; -} - -std::vector SensorsHidlTest::getInjectEventSensors() { - std::vector sensors; - for (const SensorInfo& info : getSensorsList()) { - if (info.flags & static_cast(SensorFlagBits::DATA_INJECTION)) { - sensors.push_back(info); - } - } - return sensors; -} - -int32_t SensorsHidlTest::getInvalidSensorHandle() { - // Find a sensor handle that does not exist in the sensor list - int32_t maxHandle = 0; - for (const SensorInfo& sensor : getSensorsList()) { - maxHandle = std::max(maxHandle, sensor.sensorHandle); - } - return maxHandle + 1; -} - -// Test if sensor list returned is valid -TEST_P(SensorsHidlTest, SensorListValid) { +TEST_P(SensorsHidlTest, SensorListDoesntContainInvalidType) { getSensors()->getSensorsList([&](const auto& list) { const size_t count = list.size(); for (size_t i = 0; i < count; ++i) { const auto& s = list[i]; - SCOPED_TRACE(::testing::Message() - << i << "/" << count << ": " - << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') - << s.sensorHandle << std::dec << " type=" << static_cast(s.type) - << " name=" << s.name); - - // Test non-empty type string - EXPECT_FALSE(s.typeAsString.empty()); - - // Test defined type matches defined string type - EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString)); - - // Test if all sensor has name and vendor - EXPECT_FALSE(s.name.empty()); - EXPECT_FALSE(s.vendor.empty()); - - // Test power > 0, maxRange > 0 - EXPECT_LE(0, s.power); - EXPECT_LT(0, s.maxRange); - - // Info type, should have no sensor - EXPECT_FALSE(s.type == SensorType::ADDITIONAL_INFO || s.type == SensorType::META_DATA); - - // Test fifoMax >= fifoReserved - EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount) - << "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount; - - // Test Reporting mode valid - EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags))); - - // Test min max are in the right order - EXPECT_LE(s.minDelay, s.maxDelay); - // Test min/max delay matches reporting mode - EXPECT_NO_FATAL_FAILURE( - assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags))); + EXPECT_FALSE(s.type == ::android::hardware::sensors::V2_1::SensorType::HINGE_ANGLE); } }); } -// Test that SetOperationMode returns the expected value -TEST_P(SensorsHidlTest, SetOperationMode) { - std::vector sensors = getInjectEventSensors(); - if (getInjectEventSensors().size() > 0) { - 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)); - } else { - ASSERT_EQ(Result::BAD_VALUE, getSensors()->setOperationMode(OperationMode::DATA_INJECTION)); - } -} - -// Test that an injected event is written back to the Event FMQ -TEST_P(SensorsHidlTest, InjectSensorEventData) { - std::vector sensors = getInjectEventSensors(); - if (sensors.size() == 0) { - return; - } - - ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION)); - - EventCallback callback; - getEnvironment()->registerCallback(&callback); - - // AdditionalInfo event should not be sent to Event FMQ - Event additionalInfoEvent; - additionalInfoEvent.sensorType = SensorType::ADDITIONAL_INFO; - additionalInfoEvent.timestamp = android::elapsedRealtimeNano(); - - Event injectedEvent; - injectedEvent.timestamp = android::elapsedRealtimeNano(); - Vec3 data = {1, 2, 3, SensorStatus::ACCURACY_HIGH}; - injectedEvent.u.vec3 = data; - - for (const auto& s : sensors) { - additionalInfoEvent.sensorHandle = s.sensorHandle; - EXPECT_EQ(Result::OK, getSensors()->injectSensorData(additionalInfoEvent)); - - injectedEvent.sensorType = s.type; - injectedEvent.sensorHandle = s.sensorHandle; - EXPECT_EQ(Result::OK, getSensors()->injectSensorData(injectedEvent)); - } - - // Wait for events to be written back to the Event FMQ - callback.waitForEvents(sensors, milliseconds(1000) /* timeout */); - - for (const auto& s : sensors) { - auto events = callback.getEvents(s.sensorHandle); - auto lastEvent = events.back(); - - // Verify that only a single event has been received - ASSERT_EQ(events.size(), 1); - - // Verify that the event received matches the event injected and is not the additional - // info event - ASSERT_EQ(lastEvent.sensorType, s.type); - ASSERT_EQ(lastEvent.sensorType, s.type); - ASSERT_EQ(lastEvent.timestamp, injectedEvent.timestamp); - ASSERT_EQ(lastEvent.u.vec3.x, injectedEvent.u.vec3.x); - ASSERT_EQ(lastEvent.u.vec3.y, injectedEvent.u.vec3.y); - ASSERT_EQ(lastEvent.u.vec3.z, injectedEvent.u.vec3.z); - ASSERT_EQ(lastEvent.u.vec3.status, injectedEvent.u.vec3.status); - } - - getEnvironment()->unregisterCallback(); - ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); -} - -// Test if sensor hal can do UI speed accelerometer streaming properly -TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) { - testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200), - std::chrono::seconds(5), sAccelNormChecker); -} - -// Test if sensor hal can do normal speed accelerometer streaming properly -TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) { - testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20), - std::chrono::seconds(5), sAccelNormChecker); -} - -// Test if sensor hal can do game speed accelerometer streaming properly -TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) { - testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5), - std::chrono::seconds(5), sAccelNormChecker); -} - -// Test if sensor hal can do UI speed gyroscope streaming properly -TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) { - testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200), - std::chrono::seconds(5), sGyroNormChecker); -} - -// Test if sensor hal can do normal speed gyroscope streaming properly -TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) { - testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20), - std::chrono::seconds(5), sGyroNormChecker); -} - -// Test if sensor hal can do game speed gyroscope streaming properly -TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) { - testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5), - std::chrono::seconds(5), sGyroNormChecker); -} - -// Test if sensor hal can do UI speed magnetometer streaming properly -TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) { - testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200), - std::chrono::seconds(5), NullChecker()); -} - -// Test if sensor hal can do normal speed magnetometer streaming properly -TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) { - testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20), - std::chrono::seconds(5), NullChecker()); -} - -// Test if sensor hal can do game speed magnetometer streaming properly -TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) { - testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5), - std::chrono::seconds(5), NullChecker()); -} - -// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active -TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) { - testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER); - testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/); -} - -// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active -TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) { - testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE); - testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/); -} - -// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active -TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) { - testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD); - testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/); -} - -// Test if sensor hal can do accelerometer batching properly -TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) { - testBatchingOperation(SensorType::ACCELEROMETER); -} - -// Test if sensor hal can do gyroscope batching properly -TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) { - testBatchingOperation(SensorType::GYROSCOPE); -} - -// Test if sensor hal can do magnetometer batching properly -TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) { - testBatchingOperation(SensorType::MAGNETIC_FIELD); -} - -// Test sensor event direct report with ashmem for accel sensor at normal rate -TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) { - testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL, - sAccelNormChecker); -} - -// Test sensor event direct report with ashmem for accel sensor at fast rate -TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) { - testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST, - sAccelNormChecker); -} - -// Test sensor event direct report with ashmem for accel sensor at very fast rate -TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) { - testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, - RateLevel::VERY_FAST, sAccelNormChecker); -} - -// Test sensor event direct report with ashmem for gyro sensor at normal rate -TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) { - testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL, - sGyroNormChecker); -} - -// Test sensor event direct report with ashmem for gyro sensor at fast rate -TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) { - testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST, - sGyroNormChecker); -} - -// Test sensor event direct report with ashmem for gyro sensor at very fast rate -TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) { - testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST, - sGyroNormChecker); -} - -// Test sensor event direct report with ashmem for mag sensor at normal rate -TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) { - testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL, - NullChecker()); -} - -// Test sensor event direct report with ashmem for mag sensor at fast rate -TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) { - testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST, - NullChecker()); -} - -// Test sensor event direct report with ashmem for mag sensor at very fast rate -TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) { - testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, - RateLevel::VERY_FAST, NullChecker()); -} - -// Test sensor event direct report with gralloc for accel sensor at normal rate -TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) { - testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL, - sAccelNormChecker); -} - -// Test sensor event direct report with gralloc for accel sensor at fast rate -TEST_P(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_P(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_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) { - testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL, - sGyroNormChecker); -} - -// Test sensor event direct report with gralloc for gyro sensor at fast rate -TEST_P(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_P(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_P(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_P(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_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) { - testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, - RateLevel::VERY_FAST, NullChecker()); -} - -void SensorsHidlTest::activateAllSensors(bool enable) { - for (const SensorInfo& sensorInfo : getSensorsList()) { - if (isValidType(sensorInfo.type)) { - batch(sensorInfo.sensorHandle, sensorInfo.minDelay, 0 /* maxReportLatencyNs */); - activate(sensorInfo.sensorHandle, enable); - } - } -} - -// Test that if initialize is called twice, then the HAL writes events to the FMQs from the second -// call to the function. -TEST_P(SensorsHidlTest, CallInitializeTwice) { - // Create a helper class so that a second environment is able to be instantiated - class SensorsHidlEnvironmentTest : public SensorsHidlEnvironmentV2_0 { - public: - SensorsHidlEnvironmentTest(const std::string& service_name) - : SensorsHidlEnvironmentV2_0(service_name) {} - }; - - if (getSensorsList().size() == 0) { - // No sensors - return; - } - - constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s - constexpr int32_t kNumEvents = 1; - - // Create a new environment that calls initialize() - std::unique_ptr newEnv = - std::make_unique(GetParam()); - newEnv->HidlSetUp(); - if (HasFatalFailure()) { - return; // Exit early if setting up the new environment failed - } - - activateAllSensors(true); - // Verify that the old environment does not receive any events - ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0); - // Verify that the new event queue receives sensor events - ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, newEnv.get()).size(), kNumEvents); - activateAllSensors(false); - - // Cleanup the test environment - newEnv->HidlTearDown(); - - // Restore the test environment for future tests - getEnvironment()->HidlTearDown(); - getEnvironment()->HidlSetUp(); - if (HasFatalFailure()) { - return; // Exit early if resetting the environment failed - } - - // Ensure that the original environment is receiving events - activateAllSensors(true); - ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents); - activateAllSensors(false); -} - -TEST_P(SensorsHidlTest, CleanupConnectionsOnInitialize) { - activateAllSensors(true); - - // Verify that events are received - constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s - constexpr int32_t kNumEvents = 1; - ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), kNumEvents); - - // Clear the active sensor handles so they are not disabled during TearDown - auto handles = mSensorHandles; - mSensorHandles.clear(); - getEnvironment()->HidlTearDown(); - getEnvironment()->HidlSetUp(); - if (HasFatalFailure()) { - return; // Exit early if resetting the environment failed - } - - // Verify no events are received until sensors are re-activated - ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0); - activateAllSensors(true); - ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), kNumEvents); - - // Disable sensors - activateAllSensors(false); - - // Restore active sensors prior to clearing the environment - mSensorHandles = handles; -} - -void SensorsHidlTest::runSingleFlushTest(const std::vector& sensors, - bool activateSensor, int32_t expectedFlushCount, - Result expectedResponse) { - runFlushTest(sensors, activateSensor, 1 /* flushCalls */, expectedFlushCount, expectedResponse); -} - -void SensorsHidlTest::runFlushTest(const std::vector& sensors, bool activateSensor, - int32_t flushCalls, int32_t expectedFlushCount, - Result expectedResponse) { - EventCallback callback; - getEnvironment()->registerCallback(&callback); - - for (const SensorInfo& sensor : sensors) { - // Configure and activate the sensor - batch(sensor.sensorHandle, sensor.maxDelay, 0 /* maxReportLatencyNs */); - activate(sensor.sensorHandle, activateSensor); - - // Flush the sensor - for (int32_t i = 0; i < flushCalls; i++) { - Result flushResult = flush(sensor.sensorHandle); - ASSERT_EQ(flushResult, expectedResponse); - } - } - - // Wait up to one second for the flush events - callback.waitForFlushEvents(sensors, flushCalls, milliseconds(1000) /* timeout */); - - // Deactivate all sensors after waiting for flush events so pending flush events are not - // abandoned by the HAL. - for (const SensorInfo& sensor : sensors) { - activate(sensor.sensorHandle, false); - } - getEnvironment()->unregisterCallback(); - - // Check that the correct number of flushes are present for each sensor - for (const SensorInfo& sensor : sensors) { - ASSERT_EQ(callback.getFlushCount(sensor.sensorHandle), expectedFlushCount); - } -} - -TEST_P(SensorsHidlTest, FlushSensor) { - // Find a sensor that is not a one-shot sensor - std::vector sensors = getNonOneShotSensors(); - if (sensors.size() == 0) { - return; - } - - constexpr int32_t kFlushes = 5; - runSingleFlushTest(sensors, true /* activateSensor */, 1 /* expectedFlushCount */, Result::OK); - runFlushTest(sensors, true /* activateSensor */, kFlushes, kFlushes, Result::OK); -} - -TEST_P(SensorsHidlTest, FlushOneShotSensor) { - // Find a sensor that is a one-shot sensor - std::vector sensors = getOneShotSensors(); - if (sensors.size() == 0) { - return; - } - - runSingleFlushTest(sensors, true /* activateSensor */, 0 /* expectedFlushCount */, - Result::BAD_VALUE); -} - -TEST_P(SensorsHidlTest, FlushInactiveSensor) { - // Attempt to find a non-one shot sensor, then a one-shot sensor if necessary - std::vector sensors = getNonOneShotSensors(); - if (sensors.size() == 0) { - sensors = getOneShotSensors(); - if (sensors.size() == 0) { - return; - } - } - - runSingleFlushTest(sensors, false /* activateSensor */, 0 /* expectedFlushCount */, - Result::BAD_VALUE); -} - -TEST_P(SensorsHidlTest, FlushNonexistentSensor) { - SensorInfo sensor; - std::vector sensors = getNonOneShotSensors(); - if (sensors.size() == 0) { - sensors = getOneShotSensors(); - if (sensors.size() == 0) { - return; - } - } - sensor = sensors.front(); - sensor.sensorHandle = getInvalidSensorHandle(); - runSingleFlushTest(std::vector{sensor}, false /* activateSensor */, - 0 /* expectedFlushCount */, Result::BAD_VALUE); -} - -TEST_P(SensorsHidlTest, Batch) { - if (getSensorsList().size() == 0) { - return; - } - - activateAllSensors(false /* enable */); - for (const SensorInfo& sensor : getSensorsList()) { - // Call batch on inactive sensor - // One shot sensors have minDelay set to -1 which is an invalid - // parameter. Use 0 instead to avoid errors. - int64_t samplingPeriodNs = extractReportMode(sensor.flags) == SensorFlagBits::ONE_SHOT_MODE - ? 0 - : sensor.minDelay; - ASSERT_EQ(batch(sensor.sensorHandle, samplingPeriodNs, 0 /* maxReportLatencyNs */), - Result::OK); - - // Activate the sensor - activate(sensor.sensorHandle, true /* enabled */); - - // Call batch on an active sensor - ASSERT_EQ(batch(sensor.sensorHandle, sensor.maxDelay, 0 /* maxReportLatencyNs */), - Result::OK); - } - activateAllSensors(false /* enable */); - - // Call batch on an invalid sensor - SensorInfo sensor = getSensorsList().front(); - sensor.sensorHandle = getInvalidSensorHandle(); - ASSERT_EQ(batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */), - Result::BAD_VALUE); -} - -TEST_P(SensorsHidlTest, Activate) { - if (getSensorsList().size() == 0) { - return; - } - - // Verify that sensor events are generated when activate is called - for (const SensorInfo& sensor : getSensorsList()) { - batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */); - ASSERT_EQ(activate(sensor.sensorHandle, true), Result::OK); - - // Call activate on a sensor that is already activated - ASSERT_EQ(activate(sensor.sensorHandle, true), Result::OK); - - // Deactivate the sensor - ASSERT_EQ(activate(sensor.sensorHandle, false), Result::OK); - - // Call deactivate on a sensor that is already deactivated - ASSERT_EQ(activate(sensor.sensorHandle, false), Result::OK); - } - - // Attempt to activate an invalid sensor - int32_t invalidHandle = getInvalidSensorHandle(); - ASSERT_EQ(activate(invalidHandle, true), Result::BAD_VALUE); - ASSERT_EQ(activate(invalidHandle, false), Result::BAD_VALUE); -} - -TEST_P(SensorsHidlTest, NoStaleEvents) { - constexpr milliseconds kFiveHundredMs(500); - constexpr milliseconds kOneSecond(1000); - - // Register the callback to receive sensor events - EventCallback callback; - getEnvironment()->registerCallback(&callback); - - // This test is not valid for one-shot or special-report-mode sensors - const std::vector sensors = getNonOneShotAndNonSpecialSensors(); - milliseconds maxMinDelay(0); - for (const SensorInfo& sensor : sensors) { - milliseconds minDelay = duration_cast(microseconds(sensor.minDelay)); - maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count())); - } - - // Activate the sensors so that they start generating events - activateAllSensors(true); - - // According to the CDD, the first sample must be generated within 400ms + 2 * sample_time - // and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount - // of time to guarantee that a sample has arrived. - callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); - activateAllSensors(false); - - // Save the last received event for each sensor - std::map lastEventTimestampMap; - for (const SensorInfo& sensor : sensors) { - // Some on-change sensors may not report an event without stimulus - if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) { - ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1); - } - if (callback.getEvents(sensor.sensorHandle).size() >= 1) { - lastEventTimestampMap[sensor.sensorHandle] = - callback.getEvents(sensor.sensorHandle).back().timestamp; - } - } - - // Allow some time to pass, reset the callback, then reactivate the sensors - usleep(duration_cast(kOneSecond + (5 * maxMinDelay)).count()); - callback.reset(); - activateAllSensors(true); - callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); - activateAllSensors(false); - - for (const SensorInfo& sensor : sensors) { - // Skip sensors that did not previously report an event - if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) { - continue; - } - // Skip on-change sensors that do not consistently report an initial event - if (callback.getEvents(sensor.sensorHandle).size() < 1) { - continue; - } - // Ensure that the first event received is not stale by ensuring that its timestamp is - // sufficiently different from the previous event - const Event newEvent = callback.getEvents(sensor.sensorHandle).front(); - milliseconds delta = duration_cast( - nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle])); - milliseconds sensorMinDelay = duration_cast(microseconds(sensor.minDelay)); - ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay)); - } -} - -void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, - RateLevel rateLevel) { - configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel, - [&](Result result, int32_t reportToken) { - if (isDirectReportRateSupported(sensor, rateLevel)) { - ASSERT_EQ(result, Result::OK); - if (rateLevel != RateLevel::STOP) { - ASSERT_GT(reportToken, 0); - } - } else { - ASSERT_EQ(result, Result::BAD_VALUE); - } - }); -} - -void SensorsHidlTest::queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType, - bool* supportsAnyDirectChannel) { - *supportsSharedMemType = false; - *supportsAnyDirectChannel = false; - for (const SensorInfo& curSensor : getSensorsList()) { - if (isDirectChannelTypeSupported(curSensor, memType)) { - *supportsSharedMemType = true; - } - if (isDirectChannelTypeSupported(curSensor, SharedMemType::ASHMEM) || - isDirectChannelTypeSupported(curSensor, SharedMemType::GRALLOC)) { - *supportsAnyDirectChannel = true; - } - - if (*supportsSharedMemType && *supportsAnyDirectChannel) { - break; - } - } -} - -void SensorsHidlTest::verifyRegisterDirectChannel(std::shared_ptr mem, - int32_t* directChannelHandle, - bool supportsSharedMemType, - bool supportsAnyDirectChannel) { - char* buffer = mem->getBuffer(); - memset(buffer, 0xff, mem->getSize()); - - registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) { - if (supportsSharedMemType) { - ASSERT_EQ(result, Result::OK); - ASSERT_GT(channelHandle, 0); - - // Verify that the memory has been zeroed - for (size_t i = 0; i < mem->getSize(); i++) { - ASSERT_EQ(buffer[i], 0x00); - } - } else { - Result expectedResult = - supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION; - ASSERT_EQ(result, expectedResult); - ASSERT_EQ(channelHandle, -1); - } - *directChannelHandle = channelHandle; - }); -} - -void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType memType, - int32_t directChannelHandle, bool supportsAnyDirectChannel) { - if (isDirectChannelTypeSupported(sensor, memType)) { - // Verify that each rate level is properly supported - checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL); - checkRateLevel(sensor, directChannelHandle, RateLevel::FAST); - checkRateLevel(sensor, directChannelHandle, RateLevel::VERY_FAST); - checkRateLevel(sensor, directChannelHandle, RateLevel::STOP); - - // Verify that a sensor handle of -1 is only acceptable when using RateLevel::STOP - configDirectReport( - -1 /* sensorHandle */, directChannelHandle, RateLevel::NORMAL, - [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); }); - configDirectReport( - -1 /* sensorHandle */, directChannelHandle, RateLevel::STOP, - [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); }); - } 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 - Result expectedResult = - supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION; - configDirectReport(sensor.sensorHandle, directChannelHandle, RateLevel::NORMAL, - [expectedResult](Result result, int32_t /* reportToken */) { - ASSERT_EQ(result, expectedResult); - }); - } -} - -void SensorsHidlTest::verifyUnregisterDirectChannel(int32_t directChannelHandle, - bool supportsAnyDirectChannel) { - Result expectedResult = supportsAnyDirectChannel ? Result::OK : Result::INVALID_OPERATION; - ASSERT_EQ(unregisterDirectChannel(directChannelHandle), expectedResult); -} - -void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) { - constexpr size_t kNumEvents = 1; - constexpr size_t kMemSize = kNumEvents * kEventSize; - - std::shared_ptr mem( - SensorsTestSharedMemory::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); - } -} - -TEST_P(SensorsHidlTest, DirectChannelAshmem) { - verifyDirectChannel(SharedMemType::ASHMEM); -} - -TEST_P(SensorsHidlTest, DirectChannelGralloc) { - verifyDirectChannel(SharedMemType::GRALLOC); -} - -bool SensorsHidlTest::getDirectChannelSensor(SensorInfo* sensor, SharedMemType* memType, - RateLevel* rate) { - bool found = false; - for (const SensorInfo& curSensor : getSensorsList()) { - if (isDirectChannelTypeSupported(curSensor, SharedMemType::ASHMEM)) { - *memType = SharedMemType::ASHMEM; - *sensor = curSensor; - found = true; - break; - } else if (isDirectChannelTypeSupported(curSensor, SharedMemType::GRALLOC)) { - *memType = SharedMemType::GRALLOC; - *sensor = curSensor; - found = true; - break; - } - } - - if (found) { - // Find a supported rate level - constexpr int kNumRateLevels = 3; - RateLevel rates[kNumRateLevels] = {RateLevel::NORMAL, RateLevel::FAST, - RateLevel::VERY_FAST}; - *rate = RateLevel::STOP; - for (int i = 0; i < kNumRateLevels; i++) { - if (isDirectReportRateSupported(*sensor, rates[i])) { - *rate = rates[i]; - } - } - - // At least one rate level must be supported - EXPECT_NE(*rate, RateLevel::STOP); - } - return found; -} - -TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) { - SensorInfo sensor; - SharedMemType memType; - RateLevel rate; - if (!getDirectChannelSensor(&sensor, &memType, &rate)) { - return; - } - - // Verify that an invalid channel handle produces a BAD_VALUE result - configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) { - ASSERT_EQ(result, Result::BAD_VALUE); - }); -} - -TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) { - constexpr size_t kNumEvents = 1; - constexpr size_t kMemSize = kNumEvents * kEventSize; - - SensorInfo sensor; - SharedMemType memType; - RateLevel rate; - - if (!getDirectChannelSensor(&sensor, &memType, &rate)) { - return; - } - - std::shared_ptr mem( - SensorsTestSharedMemory::create(memType, kMemSize)); - ASSERT_NE(mem, nullptr); - - int32_t directChannelHandle = 0; - registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) { - ASSERT_EQ(result, Result::OK); - directChannelHandle = channelHandle; - }); - - // Configure the channel and expect success - configDirectReport( - sensor.sensorHandle, directChannelHandle, rate, - [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); }); - - // Call initialize() via the environment setup to cause the HAL to re-initialize - // Clear the active direct connections so they are not stopped during TearDown - auto handles = mDirectChannelHandles; - mDirectChannelHandles.clear(); - getEnvironment()->HidlTearDown(); - getEnvironment()->HidlSetUp(); - if (HasFatalFailure()) { - return; // Exit early if resetting the environment failed - } - - // Attempt to configure the direct channel and expect it to fail - configDirectReport( - sensor.sensorHandle, directChannelHandle, rate, - [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); }); - - // Restore original handles, though they should already be deactivated - mDirectChannelHandles = handles; -} - INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames( android::hardware::sensors::V2_0::ISensors::descriptor)), - android::hardware::PrintInstanceNameToString); -// vim: set ts=2 sw=2 + android::hardware::PrintInstanceNameToString); \ No newline at end of file diff --git a/sensors/2.1/vts/functional/Android.bp b/sensors/2.1/vts/functional/Android.bp new file mode 100644 index 0000000000..c92bab3373 --- /dev/null +++ b/sensors/2.1/vts/functional/Android.bp @@ -0,0 +1,48 @@ +// +// Copyright (C) 2018 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. +// + +cc_test { + name: "VtsHalSensorsV2_1TargetTest", + cflags: [ + "-DLOG_TAG=\"sensors_hidl_hal_test\"", + "-DSENSORS_HAL_2_1", + ], + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "VtsHalSensorsV2_1TargetTest.cpp", + ], + header_libs: [ + "android.hardware.sensors@2.X-shared-utils", + ], + static_libs: [ + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@3.0", + "android.hardware.sensors@1.0", + "android.hardware.sensors@1.0-convert", + "android.hardware.sensors@2.0", + "android.hardware.sensors@2.1", + "libfmq", + "VtsHalSensorsTargetTestUtils", + "VtsHalSensorsV2_XTargetTest", + ], + test_suites: [ + "general-tests", + "vts-core", + ], +} diff --git a/sensors/2.1/vts/functional/AndroidTest.xml b/sensors/2.1/vts/functional/AndroidTest.xml new file mode 100644 index 0000000000..0d8593e51d --- /dev/null +++ b/sensors/2.1/vts/functional/AndroidTest.xml @@ -0,0 +1,39 @@ + + + + diff --git a/sensors/2.1/vts/functional/OWNERS b/sensors/2.1/vts/functional/OWNERS new file mode 100644 index 0000000000..892da1548c --- /dev/null +++ b/sensors/2.1/vts/functional/OWNERS @@ -0,0 +1,8 @@ +# Sensors team +arthuri@google.com +bduddie@google.com +stange@google.com + +# VTS team +trong@google.com +yim@google.com diff --git a/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp b/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp new file mode 100644 index 0000000000..230bb6c2f1 --- /dev/null +++ b/sensors/2.1/vts/functional/VtsHalSensorsV2_1TargetTest.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2020 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 "VtsHalSensorsV2_XTargetTest.h" + +INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames( + android::hardware::sensors::V2_1::ISensors::descriptor)), + android::hardware::PrintInstanceNameToString); diff --git a/sensors/common/vts/2_X/Android.bp b/sensors/common/vts/2_X/Android.bp new file mode 100644 index 0000000000..8cf14866c5 --- /dev/null +++ b/sensors/common/vts/2_X/Android.bp @@ -0,0 +1,44 @@ +// +// Copyright (C) 2018 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. +// + +cc_test_library { + name: "VtsHalSensorsV2_XTargetTest", + cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""], + defaults: ["VtsHalTargetTestDefaults"], + srcs: [ + "SensorsHidlEnvironmentV2_X.cpp", + ], + export_include_dirs: ["."], + header_libs: [ + "android.hardware.sensors@2.X-shared-utils", + ], + shared_libs: [ + "libbinder", + ], + static_libs: [ + "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@3.0", + "android.hardware.sensors@1.0", + "android.hardware.sensors@1.0-convert", + "android.hardware.sensors@2.0", + "android.hardware.sensors@2.1", + "libfmq", + "VtsHalSensorsTargetTestUtils", + ], +} diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp similarity index 70% rename from sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp rename to sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp index 81db5a040c..2771d976df 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp +++ b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.cpp @@ -14,9 +14,11 @@ * limitations under the License. */ -#include "SensorsHidlEnvironmentV2_0.h" +#include "SensorsHidlEnvironmentV2_X.h" #include +#include + #include #include @@ -26,18 +28,20 @@ using ::android::hardware::EventFlag; using ::android::hardware::hidl_vec; using ::android::hardware::Return; 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_1::SensorInfo; +#ifdef SENSORS_HAL_2_1 +using ::android::hardware::sensors::V2_1::ISensors; +#else using ::android::hardware::sensors::V2_0::ISensors; -using ::android::hardware::sensors::V2_0::ISensorsCallback; +#endif +using ::android::hardware::sensors::V2_1::ISensorsCallback; 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; - void SensorsHalDeathRecipient::serviceDied( uint64_t /* cookie */, const ::android::wp<::android::hidl::base::V1_0::IBase>& /* service */) { @@ -45,48 +49,34 @@ void SensorsHalDeathRecipient::serviceDied( FAIL() << "Sensors HAL died during test"; } -struct SensorsCallback : ISensorsCallback { - Return onDynamicSensorsConnected(const hidl_vec& /* sensorInfos */) { - return Return(); - } - - Return onDynamicSensorsDisconnected(const hidl_vec& /* sensorHandles */) { - return Return(); - } -}; - -bool SensorsHidlEnvironmentV2_0::resetHal() { +bool SensorsHidlEnvironmentV2_X::resetHal() { bool succeed = false; do { - mSensors = ISensors::getService(mServiceName); + mSensors = wrapISensors(ISensors::getService(mServiceName)); if (mSensors == nullptr) { break; } mSensors->linkToDeath(mDeathRecipient, 0 /* cookie */); // 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) { + if (mWakeLockQueue == nullptr) { break; } EventFlag::deleteEventFlag(&mEventQueueFlag); - EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag); + EventFlag::createEventFlag(mSensors->getEventQueue().getEventFlagWord(), &mEventQueueFlag); if (mEventQueueFlag == nullptr) { break; } - mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(), - new SensorsCallback()); + mSensors->initialize(*mWakeLockQueue->getDesc(), new NoOpSensorsCallback()); std::vector sensorList; if (!mSensors->getSensorsList([&](const hidl_vec& list) { sensorList = list; }) - .isOk()) { + .isOk()) { break; } @@ -113,7 +103,7 @@ bool SensorsHidlEnvironmentV2_0::resetHal() { return succeed; } -void SensorsHidlEnvironmentV2_0::HidlTearDown() { +void SensorsHidlEnvironmentV2_X::HidlTearDown() { mStopThread = true; if (mEventQueueFlag != nullptr) { @@ -127,25 +117,25 @@ void SensorsHidlEnvironmentV2_0::HidlTearDown() { } } -void SensorsHidlEnvironmentV2_0::startPollingThread() { +void SensorsHidlEnvironmentV2_X::startPollingThread() { mStopThread = false; mEvents.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT); mPollThread = std::thread(pollingThread, this); } -void SensorsHidlEnvironmentV2_0::readEvents() { - size_t availableEvents = mEventQueue->availableToRead(); +void SensorsHidlEnvironmentV2_X::readEvents() { + size_t availableEvents = mSensors->getEventQueue().availableToRead(); if (availableEvents == 0) { uint32_t eventFlagState = 0; mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS), &eventFlagState); - availableEvents = mEventQueue->availableToRead(); + availableEvents = mSensors->getEventQueue().availableToRead(); } size_t eventsToRead = std::min(availableEvents, mEventBuffer.size()); if (eventsToRead > 0) { - if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) { + if (mSensors->getEventQueue().read(mEventBuffer.data(), eventsToRead)) { mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::EVENTS_READ)); for (size_t i = 0; i < eventsToRead; i++) { addEvent(mEventBuffer[i]); @@ -154,7 +144,7 @@ void SensorsHidlEnvironmentV2_0::readEvents() { } } -void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* env) { +void SensorsHidlEnvironmentV2_X::pollingThread(SensorsHidlEnvironmentV2_X* env) { ALOGD("polling thread start"); while (!env->mStopThread.load()) { diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h similarity index 68% rename from sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h rename to sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h index 819cdd45ab..01f451f5ad 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h +++ b/sensors/common/vts/2_X/SensorsHidlEnvironmentV2_X.h @@ -14,13 +14,15 @@ * limitations under the License. */ -#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H -#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H +#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H +#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H +#include "ISensorsWrapper.h" #include "sensors-vts-utils/SensorsHidlEnvironmentBase.h" -#include -#include +#include +#include + #include #include @@ -30,6 +32,10 @@ using ::android::sp; using ::android::hardware::MessageQueue; +using ::android::hardware::sensors::V2_1::implementation::ISensorsWrapperBase; +using ::android::hardware::sensors::V2_1::implementation::MAX_RECEIVE_BUFFER_EVENT_COUNT; +using ::android::hardware::sensors::V2_1::implementation::NoOpSensorsCallback; +using ::android::hardware::sensors::V2_1::implementation::wrapISensors; class SensorsHidlTest; @@ -39,14 +45,14 @@ class SensorsHalDeathRecipient : public ::android::hardware::hidl_death_recipien const ::android::wp<::android::hidl::base::V1_0::IBase>& service) override; }; -class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { - public: - using Event = ::android::hardware::sensors::V1_0::Event; +class SensorsHidlEnvironmentV2_X + : public SensorsHidlEnvironmentBase<::android::hardware::sensors::V2_1::Event> { + public: virtual void HidlTearDown() override; - protected: + protected: friend SensorsHidlTest; - SensorsHidlEnvironmentV2_0(const std::string& service_name) + SensorsHidlEnvironmentV2_X(const std::string& service_name) : SensorsHidlEnvironmentBase(service_name), mEventQueueFlag(nullptr) {} /** @@ -66,41 +72,30 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { * * @param env SensorEnvironment to being polling for events on */ - static void pollingThread(SensorsHidlEnvironmentV2_0* env); + static void pollingThread(SensorsHidlEnvironmentV2_X* env); /** * Reads and saves sensor events from the Event FMQ */ void readEvents(); - GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_0); + GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_X); /** * Pointer to the Sensors HAL Interface that allows the test to call HAL functions. */ - sp mSensors; + sp mSensors; /** * Monitors the HAL for crashes, triggering test failure if seen */ sp mDeathRecipient = new SensorsHalDeathRecipient(); - /** - * 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. @@ -113,15 +108,11 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { */ ::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; + std::array<::android::hardware::sensors::V2_1::Event, MAX_RECEIVE_BUFFER_EVENT_COUNT> + mEventBuffer; }; -#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H +#endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_X_H diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h new file mode 100644 index 0000000000..53ed259948 --- /dev/null +++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h @@ -0,0 +1,1186 @@ +/* + * Copyright (C) 2018 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 "SensorsHidlEnvironmentV2_X.h" +#include "convertV2_1.h" +#include "sensors-vts-utils/SensorsHidlTestBase.h" +#include "sensors-vts-utils/SensorsTestSharedMemory.h" + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/** + * This file contains the core tests and test logic for both sensors HAL 2.0 + * and 2.1. To make it easier to share the code between both VTS test suites, + * this is defined as a header so they can both include and use all pieces of + * code. + */ + +using ::android::sp; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::sensors::V1_0::MetaDataEventType; +using ::android::hardware::sensors::V1_0::OperationMode; +using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset; +using ::android::hardware::sensors::V1_0::SensorStatus; +using ::android::hardware::sensors::V1_0::SharedMemType; +using ::android::hardware::sensors::V1_0::Vec3; +using ::android::hardware::sensors::V2_1::implementation::convertToOldSensorInfos; +using std::chrono::duration_cast; +using std::chrono::microseconds; +using std::chrono::milliseconds; +using std::chrono::nanoseconds; + +using EventV1_0 = ::android::hardware::sensors::V1_0::Event; +using ISensorsType = ::android::hardware::sensors::V2_1::ISensors; +using SensorTypeVersion = ::android::hardware::sensors::V2_1::SensorType; +using EventType = ::android::hardware::sensors::V2_1::Event; +using SensorInfoType = ::android::hardware::sensors::V2_1::SensorInfo; +using SensorsHidlTestBaseV2_X = SensorsHidlTestBase; + +constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); + +class EventCallback : public IEventCallback { + public: + void reset() { + mFlushMap.clear(); + mEventMap.clear(); + } + + void onEvent(const EventType& event) override { + if (event.sensorType == SensorTypeVersion::META_DATA && + event.u.meta.what == MetaDataEventType::META_DATA_FLUSH_COMPLETE) { + std::unique_lock lock(mFlushMutex); + mFlushMap[event.sensorHandle]++; + mFlushCV.notify_all(); + } else if (event.sensorType != SensorTypeVersion::ADDITIONAL_INFO) { + std::unique_lock lock(mEventMutex); + mEventMap[event.sensorHandle].push_back(event); + mEventCV.notify_all(); + } + } + + int32_t getFlushCount(int32_t sensorHandle) { + std::unique_lock lock(mFlushMutex); + return mFlushMap[sensorHandle]; + } + + void waitForFlushEvents(const std::vector& sensorsToWaitFor, + int32_t numCallsToFlush, milliseconds timeout) { + std::unique_lock lock(mFlushMutex); + mFlushCV.wait_for(lock, timeout, + [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); }); + } + + const std::vector getEvents(int32_t sensorHandle) { + std::unique_lock lock(mEventMutex); + return mEventMap[sensorHandle]; + } + + void waitForEvents(const std::vector& sensorsToWaitFor, milliseconds timeout) { + std::unique_lock lock(mEventMutex); + mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); }); + } + + protected: + bool flushesReceived(const std::vector& sensorsToWaitFor, + int32_t numCallsToFlush) { + for (const SensorInfoType& sensor : sensorsToWaitFor) { + if (getFlushCount(sensor.sensorHandle) < numCallsToFlush) { + return false; + } + } + return true; + } + + bool eventsReceived(const std::vector& sensorsToWaitFor) { + for (const SensorInfoType& sensor : sensorsToWaitFor) { + if (getEvents(sensor.sensorHandle).size() == 0) { + return false; + } + } + return true; + } + + std::map mFlushMap; + std::recursive_mutex mFlushMutex; + std::condition_variable_any mFlushCV; + + std::map> mEventMap; + std::recursive_mutex mEventMutex; + std::condition_variable_any mEventCV; +}; + +/** + * Define the template specific versions of the static helper methods in + * SensorsHidlTestBase used to test that hinge angle is exposed properly. + */ +template <> +SensorFlagBits expectedReportModeForType(::android::hardware::sensors::V2_1::SensorType type) { + switch (type) { + case ::android::hardware::sensors::V2_1::SensorType::HINGE_ANGLE: + return SensorFlagBits::ON_CHANGE_MODE; + default: + return expectedReportModeForType( + static_cast<::android::hardware::sensors::V1_0::SensorType>(type)); + } +} + +template <> +void assertTypeMatchStringType(::android::hardware::sensors::V2_1::SensorType type, + const hidl_string& stringType) { + switch (type) { + case (::android::hardware::sensors::V2_1::SensorType::HINGE_ANGLE): + ASSERT_STREQ(SENSOR_STRING_TYPE_HINGE_ANGLE, stringType.c_str()); + break; + default: + assertTypeMatchStringType( + static_cast<::android::hardware::sensors::V1_0::SensorType>(type), stringType); + break; + } +} + +// The main test class for SENSORS HIDL HAL. +class SensorsHidlTest : public SensorsHidlTestBaseV2_X { + public: + virtual void SetUp() override { + mEnvironment = new SensorsHidlEnvironmentV2_X(GetParam()); + mEnvironment->HidlSetUp(); + // Ensure that we have a valid environment before performing tests + ASSERT_NE(getSensors(), nullptr); + } + + virtual void TearDown() override { mEnvironment->HidlTearDown(); } + + protected: + SensorInfoType defaultSensorByType(SensorTypeVersion type) override; + std::vector getSensorsList(); + // implementation wrapper + + Return getSensorsList(ISensorsType::getSensorsList_cb _hidl_cb) override { + return getSensors()->getSensorsList( + [&](const auto& list) { _hidl_cb(convertToOldSensorInfos(list)); }); + } + + Return activate(int32_t sensorHandle, bool enabled) override; + + Return batch(int32_t sensorHandle, int64_t samplingPeriodNs, + int64_t maxReportLatencyNs) override { + return getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); + } + + Return flush(int32_t sensorHandle) override { + return getSensors()->flush(sensorHandle); + } + + Return injectSensorData(const EventType& event) override { + return getSensors()->injectSensorData(event); + } + + Return registerDirectChannel(const SharedMemInfo& mem, + ISensorsType::registerDirectChannel_cb _hidl_cb) override; + + Return unregisterDirectChannel(int32_t channelHandle) override { + return getSensors()->unregisterDirectChannel(channelHandle); + } + + Return configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, + ISensorsType::configDirectReport_cb _hidl_cb) override { + return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); + } + + inline sp& getSensors() { return mEnvironment->mSensors; } + + SensorsHidlEnvironmentBase* getEnvironment() override { return mEnvironment; } + + // Test helpers + void runSingleFlushTest(const std::vector& sensors, bool activateSensor, + int32_t expectedFlushCount, Result expectedResponse); + void runFlushTest(const std::vector& sensors, bool activateSensor, + int32_t flushCalls, int32_t expectedFlushCount, Result expectedResponse); + + // Helper functions + void activateAllSensors(bool enable); + std::vector getNonOneShotSensors(); + std::vector getNonOneShotAndNonSpecialSensors(); + std::vector getOneShotSensors(); + std::vector getInjectEventSensors(); + int32_t getInvalidSensorHandle(); + bool getDirectChannelSensor(SensorInfoType* sensor, SharedMemType* memType, RateLevel* rate); + void verifyDirectChannel(SharedMemType memType); + void verifyRegisterDirectChannel( + std::shared_ptr> mem, + int32_t* directChannelHandle, bool supportsSharedMemType, + bool supportsAnyDirectChannel); + void verifyConfigure(const SensorInfoType& sensor, SharedMemType memType, + int32_t directChannelHandle, bool directChannelSupported); + void verifyUnregisterDirectChannel(int32_t directChannelHandle, bool directChannelSupported); + void checkRateLevel(const SensorInfoType& sensor, int32_t directChannelHandle, + RateLevel rateLevel); + void queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType, + bool* supportsAnyDirectChannel); + + private: + // Test environment for sensors HAL. + SensorsHidlEnvironmentV2_X* mEnvironment; +}; + +Return SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) { + // If activating a sensor, add the handle in a set so that when test fails it can be turned off. + // The handle is not removed when it is deactivating on purpose so that it is not necessary to + // check the return value of deactivation. Deactivating a sensor more than once does not have + // negative effect. + if (enabled) { + mSensorHandles.insert(sensorHandle); + } + return getSensors()->activate(sensorHandle, enabled); +} + +Return SensorsHidlTest::registerDirectChannel(const SharedMemInfo& mem, + ISensors::registerDirectChannel_cb cb) { + // 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. + getSensors()->registerDirectChannel(mem, [&](auto result, auto channelHandle) { + if (result == Result::OK) { + mDirectChannelHandles.insert(channelHandle); + } + cb(result, channelHandle); + }); + return Void(); +} + +SensorInfoType SensorsHidlTest::defaultSensorByType(SensorTypeVersion type) { + SensorInfoType ret; + + ret.type = (SensorTypeVersion)-1; + getSensors()->getSensorsList([&](const auto& list) { + const size_t count = list.size(); + for (size_t i = 0; i < count; ++i) { + if (list[i].type == type) { + ret = list[i]; + return; + } + } + }); + + return ret; +} + +std::vector SensorsHidlTest::getSensorsList() { + std::vector ret; + + getSensors()->getSensorsList([&](const auto& list) { + const size_t count = list.size(); + ret.reserve(list.size()); + for (size_t i = 0; i < count; ++i) { + ret.push_back(list[i]); + } + }); + + return ret; +} + +std::vector SensorsHidlTest::getNonOneShotSensors() { + std::vector sensors; + for (const SensorInfoType& info : getSensorsList()) { + if (extractReportMode(info.flags) != SensorFlagBits::ONE_SHOT_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector SensorsHidlTest::getNonOneShotAndNonSpecialSensors() { + std::vector sensors; + for (const SensorInfoType& info : getSensorsList()) { + SensorFlagBits reportMode = extractReportMode(info.flags); + if (reportMode != SensorFlagBits::ONE_SHOT_MODE && + reportMode != SensorFlagBits::SPECIAL_REPORTING_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector SensorsHidlTest::getOneShotSensors() { + std::vector sensors; + for (const SensorInfoType& info : getSensorsList()) { + if (extractReportMode(info.flags) == SensorFlagBits::ONE_SHOT_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + +std::vector SensorsHidlTest::getInjectEventSensors() { + std::vector sensors; + for (const SensorInfoType& info : getSensorsList()) { + if (info.flags & static_cast(SensorFlagBits::DATA_INJECTION)) { + sensors.push_back(info); + } + } + return sensors; +} + +int32_t SensorsHidlTest::getInvalidSensorHandle() { + // Find a sensor handle that does not exist in the sensor list + int32_t maxHandle = 0; + for (const SensorInfoType& sensor : getSensorsList()) { + maxHandle = std::max(maxHandle, sensor.sensorHandle); + } + return maxHandle + 1; +} + +// Test if sensor list returned is valid +TEST_P(SensorsHidlTest, SensorListValid) { + getSensors()->getSensorsList([&](const auto& list) { + const size_t count = list.size(); + for (size_t i = 0; i < count; ++i) { + const auto& s = list[i]; + SCOPED_TRACE(::testing::Message() + << i << "/" << count << ": " + << " handle=0x" << std::hex << std::setw(8) << std::setfill('0') + << s.sensorHandle << std::dec << " type=" << static_cast(s.type) + << " name=" << s.name); + + // Test non-empty type string + EXPECT_FALSE(s.typeAsString.empty()); + + // Test defined type matches defined string type + EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString)); + + // Test if all sensor has name and vendor + EXPECT_FALSE(s.name.empty()); + EXPECT_FALSE(s.vendor.empty()); + + // Test power > 0, maxRange > 0 + EXPECT_LE(0, s.power); + EXPECT_LT(0, s.maxRange); + + // Info type, should have no sensor + EXPECT_FALSE(s.type == SensorTypeVersion::ADDITIONAL_INFO || + s.type == SensorTypeVersion::META_DATA); + + // Test fifoMax >= fifoReserved + EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount) + << "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount; + + // Test Reporting mode valid + EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags))); + + // Test min max are in the right order + EXPECT_LE(s.minDelay, s.maxDelay); + // Test min/max delay matches reporting mode + EXPECT_NO_FATAL_FAILURE( + assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags))); + } + }); +} + +// Test that SetOperationMode returns the expected value +TEST_P(SensorsHidlTest, SetOperationMode) { + std::vector sensors = getInjectEventSensors(); + if (getInjectEventSensors().size() > 0) { + 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)); + } else { + ASSERT_EQ(Result::BAD_VALUE, getSensors()->setOperationMode(OperationMode::DATA_INJECTION)); + } +} + +// Test that an injected event is written back to the Event FMQ +TEST_P(SensorsHidlTest, InjectSensorEventData) { + std::vector sensors = getInjectEventSensors(); + if (sensors.size() == 0) { + return; + } + + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION)); + + EventCallback callback; + getEnvironment()->registerCallback(&callback); + + // AdditionalInfo event should not be sent to Event FMQ + EventType additionalInfoEvent; + additionalInfoEvent.sensorType = SensorTypeVersion::ADDITIONAL_INFO; + additionalInfoEvent.timestamp = android::elapsedRealtimeNano(); + + EventType injectedEvent; + injectedEvent.timestamp = android::elapsedRealtimeNano(); + Vec3 data = {1, 2, 3, SensorStatus::ACCURACY_HIGH}; + injectedEvent.u.vec3 = data; + + for (const auto& s : sensors) { + additionalInfoEvent.sensorHandle = s.sensorHandle; + EXPECT_EQ(Result::OK, getSensors()->injectSensorData(additionalInfoEvent)); + + injectedEvent.sensorType = s.type; + injectedEvent.sensorHandle = s.sensorHandle; + EXPECT_EQ(Result::OK, getSensors()->injectSensorData(injectedEvent)); + } + + // Wait for events to be written back to the Event FMQ + callback.waitForEvents(sensors, milliseconds(1000) /* timeout */); + + for (const auto& s : sensors) { + auto events = callback.getEvents(s.sensorHandle); + auto lastEvent = events.back(); + + // Verify that only a single event has been received + ASSERT_EQ(events.size(), 1); + + // Verify that the event received matches the event injected and is not the additional + // info event + ASSERT_EQ(lastEvent.sensorType, s.type); + ASSERT_EQ(lastEvent.sensorType, s.type); + ASSERT_EQ(lastEvent.timestamp, injectedEvent.timestamp); + ASSERT_EQ(lastEvent.u.vec3.x, injectedEvent.u.vec3.x); + ASSERT_EQ(lastEvent.u.vec3.y, injectedEvent.u.vec3.y); + ASSERT_EQ(lastEvent.u.vec3.z, injectedEvent.u.vec3.z); + ASSERT_EQ(lastEvent.u.vec3.status, injectedEvent.u.vec3.status); + } + + getEnvironment()->unregisterCallback(); + ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL)); +} + +// Test if sensor hal can do UI speed accelerometer streaming properly +TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) { + testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200), + std::chrono::seconds(5), mAccelNormChecker); +} + +// Test if sensor hal can do normal speed accelerometer streaming properly +TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) { + testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20), + std::chrono::seconds(5), mAccelNormChecker); +} + +// Test if sensor hal can do game speed accelerometer streaming properly +TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) { + testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5), + std::chrono::seconds(5), mAccelNormChecker); +} + +// Test if sensor hal can do UI speed gyroscope streaming properly +TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) { + testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200), + std::chrono::seconds(5), mGyroNormChecker); +} + +// Test if sensor hal can do normal speed gyroscope streaming properly +TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) { + testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20), + std::chrono::seconds(5), mGyroNormChecker); +} + +// Test if sensor hal can do game speed gyroscope streaming properly +TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) { + testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5), + std::chrono::seconds(5), mGyroNormChecker); +} + +// Test if sensor hal can do UI speed magnetometer streaming properly +TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) { + testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200), + std::chrono::seconds(5), NullChecker()); +} + +// Test if sensor hal can do normal speed magnetometer streaming properly +TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) { + testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20), + std::chrono::seconds(5), NullChecker()); +} + +// Test if sensor hal can do game speed magnetometer streaming properly +TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) { + testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5), + std::chrono::seconds(5), NullChecker()); +} + +// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active +TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) { + testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER); + testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/); +} + +// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active +TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) { + testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE); + testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/); +} + +// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active +TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) { + testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD); + testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/); +} + +// Test if sensor hal can do accelerometer batching properly +TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) { + testBatchingOperation(SensorTypeVersion::ACCELEROMETER); +} + +// Test if sensor hal can do gyroscope batching properly +TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) { + testBatchingOperation(SensorTypeVersion::GYROSCOPE); +} + +// Test if sensor hal can do magnetometer batching properly +TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) { + testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD); +} + +// Test sensor event direct report with ashmem for accel sensor at normal rate +TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) { + testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM, + RateLevel::NORMAL, mAccelNormChecker); +} + +// Test sensor event direct report with ashmem for accel sensor at fast rate +TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) { + testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM, + RateLevel::FAST, mAccelNormChecker); +} + +// Test sensor event direct report with ashmem for accel sensor at very fast rate +TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) { + testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM, + RateLevel::VERY_FAST, mAccelNormChecker); +} + +// Test sensor event direct report with ashmem for gyro sensor at normal rate +TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) { + testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, + RateLevel::NORMAL, mGyroNormChecker); +} + +// Test sensor event direct report with ashmem for gyro sensor at fast rate +TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) { + testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST, + mGyroNormChecker); +} + +// Test sensor event direct report with ashmem for gyro sensor at very fast rate +TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) { + testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, + RateLevel::VERY_FAST, mGyroNormChecker); +} + +// Test sensor event direct report with ashmem for mag sensor at normal rate +TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) { + testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM, + RateLevel::NORMAL, NullChecker()); +} + +// Test sensor event direct report with ashmem for mag sensor at fast rate +TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) { + testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM, + RateLevel::FAST, NullChecker()); +} + +// Test sensor event direct report with ashmem for mag sensor at very fast rate +TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) { + testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM, + RateLevel::VERY_FAST, NullChecker()); +} + +// Test sensor event direct report with gralloc for accel sensor at normal rate +TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) { + testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC, + RateLevel::NORMAL, mAccelNormChecker); +} + +// Test sensor event direct report with gralloc for accel sensor at fast rate +TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) { + testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC, + RateLevel::FAST, mAccelNormChecker); +} + +// Test sensor event direct report with gralloc for accel sensor at very fast rate +TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) { + testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC, + RateLevel::VERY_FAST, mAccelNormChecker); +} + +// Test sensor event direct report with gralloc for gyro sensor at normal rate +TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) { + testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, + RateLevel::NORMAL, mGyroNormChecker); +} + +// Test sensor event direct report with gralloc for gyro sensor at fast rate +TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) { + testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST, + mGyroNormChecker); +} + +// Test sensor event direct report with gralloc for gyro sensor at very fast rate +TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) { + testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, + RateLevel::VERY_FAST, mGyroNormChecker); +} + +// Test sensor event direct report with gralloc for mag sensor at normal rate +TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) { + testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC, + RateLevel::NORMAL, NullChecker()); +} + +// Test sensor event direct report with gralloc for mag sensor at fast rate +TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) { + testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC, + RateLevel::FAST, NullChecker()); +} + +// Test sensor event direct report with gralloc for mag sensor at very fast rate +TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) { + testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC, + RateLevel::VERY_FAST, NullChecker()); +} + +void SensorsHidlTest::activateAllSensors(bool enable) { + for (const SensorInfoType& sensorInfo : getSensorsList()) { + if (isValidType(sensorInfo.type)) { + batch(sensorInfo.sensorHandle, sensorInfo.minDelay, 0 /* maxReportLatencyNs */); + activate(sensorInfo.sensorHandle, enable); + } + } +} + +// Test that if initialize is called twice, then the HAL writes events to the FMQs from the second +// call to the function. +TEST_P(SensorsHidlTest, CallInitializeTwice) { + // Create a helper class so that a second environment is able to be instantiated + class SensorsHidlEnvironmentTest : public SensorsHidlEnvironmentV2_X { + public: + SensorsHidlEnvironmentTest(const std::string& service_name) + : SensorsHidlEnvironmentV2_X(service_name) {} + }; + + if (getSensorsList().size() == 0) { + // No sensors + return; + } + + constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s + constexpr int32_t kNumEvents = 1; + + // Create a new environment that calls initialize() + std::unique_ptr newEnv = + std::make_unique(GetParam()); + newEnv->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if setting up the new environment failed + } + + activateAllSensors(true); + // Verify that the old environment does not receive any events + EXPECT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0); + // Verify that the new event queue receives sensor events + EXPECT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, newEnv.get(), newEnv.get()).size(), + kNumEvents); + activateAllSensors(false); + + // Cleanup the test environment + newEnv->HidlTearDown(); + + // Restore the test environment for future tests + getEnvironment()->HidlTearDown(); + getEnvironment()->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } + + // Ensure that the original environment is receiving events + activateAllSensors(true); + EXPECT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents); + activateAllSensors(false); +} + +TEST_P(SensorsHidlTest, CleanupConnectionsOnInitialize) { + activateAllSensors(true); + + // Verify that events are received + constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s + constexpr int32_t kNumEvents = 1; + ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), kNumEvents); + + // Clear the active sensor handles so they are not disabled during TearDown + auto handles = mSensorHandles; + mSensorHandles.clear(); + getEnvironment()->HidlTearDown(); + getEnvironment()->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } + + // Verify no events are received until sensors are re-activated + ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0); + activateAllSensors(true); + ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), kNumEvents); + + // Disable sensors + activateAllSensors(false); + + // Restore active sensors prior to clearing the environment + mSensorHandles = handles; +} + +void SensorsHidlTest::runSingleFlushTest(const std::vector& sensors, + bool activateSensor, int32_t expectedFlushCount, + Result expectedResponse) { + runFlushTest(sensors, activateSensor, 1 /* flushCalls */, expectedFlushCount, expectedResponse); +} + +void SensorsHidlTest::runFlushTest(const std::vector& sensors, bool activateSensor, + int32_t flushCalls, int32_t expectedFlushCount, + Result expectedResponse) { + EventCallback callback; + getEnvironment()->registerCallback(&callback); + + for (const SensorInfoType& sensor : sensors) { + // Configure and activate the sensor + batch(sensor.sensorHandle, sensor.maxDelay, 0 /* maxReportLatencyNs */); + activate(sensor.sensorHandle, activateSensor); + + // Flush the sensor + for (int32_t i = 0; i < flushCalls; i++) { + Result flushResult = flush(sensor.sensorHandle); + ASSERT_EQ(flushResult, expectedResponse); + } + } + + // Wait up to one second for the flush events + callback.waitForFlushEvents(sensors, flushCalls, milliseconds(1000) /* timeout */); + + // Deactivate all sensors after waiting for flush events so pending flush events are not + // abandoned by the HAL. + for (const SensorInfoType& sensor : sensors) { + activate(sensor.sensorHandle, false); + } + getEnvironment()->unregisterCallback(); + + // Check that the correct number of flushes are present for each sensor + for (const SensorInfoType& sensor : sensors) { + ASSERT_EQ(callback.getFlushCount(sensor.sensorHandle), expectedFlushCount); + } +} + +TEST_P(SensorsHidlTest, FlushSensor) { + // Find a sensor that is not a one-shot sensor + std::vector sensors = getNonOneShotSensors(); + if (sensors.size() == 0) { + return; + } + + constexpr int32_t kFlushes = 5; + runSingleFlushTest(sensors, true /* activateSensor */, 1 /* expectedFlushCount */, Result::OK); + runFlushTest(sensors, true /* activateSensor */, kFlushes, kFlushes, Result::OK); +} + +TEST_P(SensorsHidlTest, FlushOneShotSensor) { + // Find a sensor that is a one-shot sensor + std::vector sensors = getOneShotSensors(); + if (sensors.size() == 0) { + return; + } + + runSingleFlushTest(sensors, true /* activateSensor */, 0 /* expectedFlushCount */, + Result::BAD_VALUE); +} + +TEST_P(SensorsHidlTest, FlushInactiveSensor) { + // Attempt to find a non-one shot sensor, then a one-shot sensor if necessary + std::vector sensors = getNonOneShotSensors(); + if (sensors.size() == 0) { + sensors = getOneShotSensors(); + if (sensors.size() == 0) { + return; + } + } + + runSingleFlushTest(sensors, false /* activateSensor */, 0 /* expectedFlushCount */, + Result::BAD_VALUE); +} + +TEST_P(SensorsHidlTest, FlushNonexistentSensor) { + SensorInfoType sensor; + std::vector sensors = getNonOneShotSensors(); + if (sensors.size() == 0) { + sensors = getOneShotSensors(); + if (sensors.size() == 0) { + return; + } + } + sensor = sensors.front(); + sensor.sensorHandle = getInvalidSensorHandle(); + runSingleFlushTest(std::vector{sensor}, false /* activateSensor */, + 0 /* expectedFlushCount */, Result::BAD_VALUE); +} + +TEST_P(SensorsHidlTest, Batch) { + if (getSensorsList().size() == 0) { + return; + } + + activateAllSensors(false /* enable */); + for (const SensorInfoType& sensor : getSensorsList()) { + // Call batch on inactive sensor + // One shot sensors have minDelay set to -1 which is an invalid + // parameter. Use 0 instead to avoid errors. + int64_t samplingPeriodNs = extractReportMode(sensor.flags) == SensorFlagBits::ONE_SHOT_MODE + ? 0 + : sensor.minDelay; + ASSERT_EQ(batch(sensor.sensorHandle, samplingPeriodNs, 0 /* maxReportLatencyNs */), + Result::OK); + + // Activate the sensor + activate(sensor.sensorHandle, true /* enabled */); + + // Call batch on an active sensor + ASSERT_EQ(batch(sensor.sensorHandle, sensor.maxDelay, 0 /* maxReportLatencyNs */), + Result::OK); + } + activateAllSensors(false /* enable */); + + // Call batch on an invalid sensor + SensorInfoType sensor = getSensorsList().front(); + sensor.sensorHandle = getInvalidSensorHandle(); + ASSERT_EQ(batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */), + Result::BAD_VALUE); +} + +TEST_P(SensorsHidlTest, Activate) { + if (getSensorsList().size() == 0) { + return; + } + + // Verify that sensor events are generated when activate is called + for (const SensorInfoType& sensor : getSensorsList()) { + batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */); + ASSERT_EQ(activate(sensor.sensorHandle, true), Result::OK); + + // Call activate on a sensor that is already activated + ASSERT_EQ(activate(sensor.sensorHandle, true), Result::OK); + + // Deactivate the sensor + ASSERT_EQ(activate(sensor.sensorHandle, false), Result::OK); + + // Call deactivate on a sensor that is already deactivated + ASSERT_EQ(activate(sensor.sensorHandle, false), Result::OK); + } + + // Attempt to activate an invalid sensor + int32_t invalidHandle = getInvalidSensorHandle(); + ASSERT_EQ(activate(invalidHandle, true), Result::BAD_VALUE); + ASSERT_EQ(activate(invalidHandle, false), Result::BAD_VALUE); +} + +TEST_P(SensorsHidlTest, NoStaleEvents) { + constexpr milliseconds kFiveHundredMs(500); + constexpr milliseconds kOneSecond(1000); + + // Register the callback to receive sensor events + EventCallback callback; + getEnvironment()->registerCallback(&callback); + + // This test is not valid for one-shot or special-report-mode sensors + const std::vector sensors = getNonOneShotAndNonSpecialSensors(); + milliseconds maxMinDelay(0); + for (const SensorInfoType& sensor : sensors) { + milliseconds minDelay = duration_cast(microseconds(sensor.minDelay)); + maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count())); + } + + // Activate the sensors so that they start generating events + activateAllSensors(true); + + // According to the CDD, the first sample must be generated within 400ms + 2 * sample_time + // and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount + // of time to guarantee that a sample has arrived. + callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); + activateAllSensors(false); + + // Save the last received event for each sensor + std::map lastEventTimestampMap; + for (const SensorInfoType& sensor : sensors) { + // Some on-change sensors may not report an event without stimulus + if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) { + ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1); + } + if (callback.getEvents(sensor.sensorHandle).size() >= 1) { + lastEventTimestampMap[sensor.sensorHandle] = + callback.getEvents(sensor.sensorHandle).back().timestamp; + } + } + + // Allow some time to pass, reset the callback, then reactivate the sensors + usleep(duration_cast(kOneSecond + (5 * maxMinDelay)).count()); + callback.reset(); + activateAllSensors(true); + callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); + activateAllSensors(false); + + for (const SensorInfoType& sensor : sensors) { + // Skip sensors that did not previously report an event + if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) { + continue; + } + // Skip on-change sensors that do not consistently report an initial event + if (callback.getEvents(sensor.sensorHandle).size() < 1) { + continue; + } + // Ensure that the first event received is not stale by ensuring that its timestamp is + // sufficiently different from the previous event + const EventType newEvent = callback.getEvents(sensor.sensorHandle).front(); + milliseconds delta = duration_cast( + nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle])); + milliseconds sensorMinDelay = duration_cast(microseconds(sensor.minDelay)); + ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay)); + } +} + +void SensorsHidlTest::checkRateLevel(const SensorInfoType& sensor, int32_t directChannelHandle, + RateLevel rateLevel) { + configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel, + [&](Result result, int32_t reportToken) { + if (isDirectReportRateSupported(sensor, rateLevel)) { + ASSERT_EQ(result, Result::OK); + if (rateLevel != RateLevel::STOP) { + ASSERT_GT(reportToken, 0); + } + } else { + ASSERT_EQ(result, Result::BAD_VALUE); + } + }); +} + +void SensorsHidlTest::queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType, + bool* supportsAnyDirectChannel) { + *supportsSharedMemType = false; + *supportsAnyDirectChannel = false; + for (const SensorInfoType& curSensor : getSensorsList()) { + if (isDirectChannelTypeSupported(curSensor, memType)) { + *supportsSharedMemType = true; + } + if (isDirectChannelTypeSupported(curSensor, SharedMemType::ASHMEM) || + isDirectChannelTypeSupported(curSensor, SharedMemType::GRALLOC)) { + *supportsAnyDirectChannel = true; + } + + if (*supportsSharedMemType && *supportsAnyDirectChannel) { + break; + } + } +} + +void SensorsHidlTest::verifyRegisterDirectChannel( + std::shared_ptr> mem, + int32_t* directChannelHandle, bool supportsSharedMemType, bool supportsAnyDirectChannel) { + char* buffer = mem->getBuffer(); + memset(buffer, 0xff, mem->getSize()); + + registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) { + if (supportsSharedMemType) { + ASSERT_EQ(result, Result::OK); + ASSERT_GT(channelHandle, 0); + + // Verify that the memory has been zeroed + for (size_t i = 0; i < mem->getSize(); i++) { + ASSERT_EQ(buffer[i], 0x00); + } + } else { + Result expectedResult = + supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION; + ASSERT_EQ(result, expectedResult); + ASSERT_EQ(channelHandle, -1); + } + *directChannelHandle = channelHandle; + }); +} + +void SensorsHidlTest::verifyConfigure(const SensorInfoType& sensor, SharedMemType memType, + int32_t directChannelHandle, bool supportsAnyDirectChannel) { + if (isDirectChannelTypeSupported(sensor, memType)) { + // Verify that each rate level is properly supported + checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL); + checkRateLevel(sensor, directChannelHandle, RateLevel::FAST); + checkRateLevel(sensor, directChannelHandle, RateLevel::VERY_FAST); + checkRateLevel(sensor, directChannelHandle, RateLevel::STOP); + + // Verify that a sensor handle of -1 is only acceptable when using RateLevel::STOP + configDirectReport(-1 /* sensorHandle */, directChannelHandle, RateLevel::NORMAL, + [](Result result, int32_t /* reportToken */) { + ASSERT_EQ(result, Result::BAD_VALUE); + }); + configDirectReport( + -1 /* sensorHandle */, directChannelHandle, RateLevel::STOP, + [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); }); + } 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 + Result expectedResult = + supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION; + configDirectReport(sensor.sensorHandle, directChannelHandle, RateLevel::NORMAL, + [expectedResult](Result result, int32_t /* reportToken */) { + ASSERT_EQ(result, expectedResult); + }); + } +} + +void SensorsHidlTest::verifyUnregisterDirectChannel(int32_t directChannelHandle, + bool supportsAnyDirectChannel) { + Result expectedResult = supportsAnyDirectChannel ? Result::OK : Result::INVALID_OPERATION; + ASSERT_EQ(unregisterDirectChannel(directChannelHandle), expectedResult); +} + +void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) { + constexpr size_t kNumEvents = 1; + constexpr size_t kMemSize = kNumEvents * kEventSize; + + std::shared_ptr> mem( + SensorsTestSharedMemory::create(memType, kMemSize)); + ASSERT_NE(mem, nullptr); + + bool supportsSharedMemType; + bool supportsAnyDirectChannel; + queryDirectChannelSupport(memType, &supportsSharedMemType, &supportsAnyDirectChannel); + + for (const SensorInfoType& sensor : getSensorsList()) { + int32_t directChannelHandle = 0; + verifyRegisterDirectChannel(mem, &directChannelHandle, supportsSharedMemType, + supportsAnyDirectChannel); + verifyConfigure(sensor, memType, directChannelHandle, supportsAnyDirectChannel); + verifyUnregisterDirectChannel(directChannelHandle, supportsAnyDirectChannel); + } +} + +TEST_P(SensorsHidlTest, DirectChannelAshmem) { + verifyDirectChannel(SharedMemType::ASHMEM); +} + +TEST_P(SensorsHidlTest, DirectChannelGralloc) { + verifyDirectChannel(SharedMemType::GRALLOC); +} + +bool SensorsHidlTest::getDirectChannelSensor(SensorInfoType* sensor, SharedMemType* memType, + RateLevel* rate) { + bool found = false; + for (const SensorInfoType& curSensor : getSensorsList()) { + if (isDirectChannelTypeSupported(curSensor, SharedMemType::ASHMEM)) { + *memType = SharedMemType::ASHMEM; + *sensor = curSensor; + found = true; + break; + } else if (isDirectChannelTypeSupported(curSensor, SharedMemType::GRALLOC)) { + *memType = SharedMemType::GRALLOC; + *sensor = curSensor; + found = true; + break; + } + } + + if (found) { + // Find a supported rate level + constexpr int kNumRateLevels = 3; + RateLevel rates[kNumRateLevels] = {RateLevel::NORMAL, RateLevel::FAST, + RateLevel::VERY_FAST}; + *rate = RateLevel::STOP; + for (int i = 0; i < kNumRateLevels; i++) { + if (isDirectReportRateSupported(*sensor, rates[i])) { + *rate = rates[i]; + } + } + + // At least one rate level must be supported + EXPECT_NE(*rate, RateLevel::STOP); + } + return found; +} + +TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) { + SensorInfoType sensor; + SharedMemType memType; + RateLevel rate; + if (!getDirectChannelSensor(&sensor, &memType, &rate)) { + return; + } + + // Verify that an invalid channel handle produces a BAD_VALUE result + configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) { + ASSERT_EQ(result, Result::BAD_VALUE); + }); +} + +TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) { + constexpr size_t kNumEvents = 1; + constexpr size_t kMemSize = kNumEvents * kEventSize; + + SensorInfoType sensor; + SharedMemType memType; + RateLevel rate; + + if (!getDirectChannelSensor(&sensor, &memType, &rate)) { + return; + } + + std::shared_ptr> mem( + SensorsTestSharedMemory::create(memType, kMemSize)); + ASSERT_NE(mem, nullptr); + + int32_t directChannelHandle = 0; + registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) { + ASSERT_EQ(result, Result::OK); + directChannelHandle = channelHandle; + }); + + // Configure the channel and expect success + configDirectReport( + sensor.sensorHandle, directChannelHandle, rate, + [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); }); + + // Call initialize() via the environment setup to cause the HAL to re-initialize + // Clear the active direct connections so they are not stopped during TearDown + auto handles = mDirectChannelHandles; + mDirectChannelHandles.clear(); + getEnvironment()->HidlTearDown(); + getEnvironment()->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } + + // Attempt to configure the direct channel and expect it to fail + configDirectReport( + sensor.sensorHandle, directChannelHandle, rate, + [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); }); + + // Restore original handles, though they should already be deactivated + mDirectChannelHandles = handles; +} diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp index bb4d329fba..ca4346a963 100644 --- a/sensors/common/vts/utils/Android.bp +++ b/sensors/common/vts/utils/Android.bp @@ -20,9 +20,6 @@ cc_library_static { cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""], srcs: [ "GrallocWrapper.cpp", - "SensorsHidlEnvironmentBase.cpp", - "SensorsHidlTestBase.cpp", - "SensorsTestSharedMemory.cpp", ], export_include_dirs: [ "include", @@ -30,6 +27,9 @@ cc_library_static { local_include_dirs: [ "include/sensors-vts-utils", ], + shared_libs: [ + "libutils", + ], static_libs: [ "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.allocator@3.0", @@ -37,5 +37,7 @@ cc_library_static { "android.hardware.graphics.mapper@2.1", "android.hardware.graphics.mapper@3.0", "android.hardware.sensors@1.0", + "android.hardware.sensors@2.0", + "android.hardware.sensors@2.1", ], } diff --git a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp deleted file mode 100644 index fa0e2e9bf0..0000000000 --- a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2018 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 "SensorsHidlEnvironmentBase.h" - -void SensorsHidlEnvironmentBase::HidlSetUp() { - ASSERT_TRUE(resetHal()) << "could not get hidl service"; - - mCollectionEnabled = false; - startPollingThread(); - - // In case framework just stopped for test and there is sensor events in the pipe, - // wait some time for those events to be cleared to avoid them messing up the test. - std::this_thread::sleep_for(std::chrono::seconds(3)); -} - -void SensorsHidlEnvironmentBase::HidlTearDown() { - mStopThread = true; - if (mPollThread.joinable()) { - mPollThread.detach(); - } -} - -void SensorsHidlEnvironmentBase::catEvents(std::vector* output) { - std::lock_guard lock(mEventsMutex); - if (output) { - output->insert(output->end(), mEvents.begin(), mEvents.end()); - } - mEvents.clear(); -} - -void SensorsHidlEnvironmentBase::setCollection(bool enable) { - std::lock_guard lock(mEventsMutex); - mCollectionEnabled = enable; -} - -void SensorsHidlEnvironmentBase::addEvent(const Event& ev) { - std::lock_guard lock(mEventsMutex); - if (mCollectionEnabled) { - mEvents.push_back(ev); - } - - if (mCallback != nullptr) { - mCallback->onEvent(ev); - } -} - -void SensorsHidlEnvironmentBase::registerCallback(IEventCallback* callback) { - std::lock_guard lock(mEventsMutex); - mCallback = callback; -} - -void SensorsHidlEnvironmentBase::unregisterCallback() { - std::lock_guard lock(mEventsMutex); - mCallback = nullptr; -} \ No newline at end of file diff --git a/sensors/common/vts/utils/SensorsHidlTestBase.cpp b/sensors/common/vts/utils/SensorsHidlTestBase.cpp deleted file mode 100644 index 18549dfb17..0000000000 --- a/sensors/common/vts/utils/SensorsHidlTestBase.cpp +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright (C) 2018 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 "SensorsHidlTestBase.h" - -#include "sensors-vts-utils/GrallocWrapper.h" -#include "sensors-vts-utils/SensorsTestSharedMemory.h" - -#include // for sensor type strings -#include -#include - -#include - -using ::android::sp; -using ::android::hardware::hidl_string; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::hardware::sensors::V1_0::SensorFlagShift; -using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset; - -const Vec3NormChecker SensorsHidlTestBase::sAccelNormChecker( - Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/)); -const Vec3NormChecker SensorsHidlTestBase::sGyroNormChecker( - Vec3NormChecker::byNominal(0.f, 0.1f /*rad/s*/)); - -std::vector SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit, - bool clearBeforeStart, - bool changeCollection) { - return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart, - changeCollection); -} - -std::vector SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit, - SensorsHidlEnvironmentBase* environment, - bool clearBeforeStart, - bool changeCollection) { - std::vector events; - constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000; // granularity 100 ms - - ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs, - clearBeforeStart); - - if (changeCollection) { - environment->setCollection(true); - } - if (clearBeforeStart) { - environment->catEvents(nullptr); - } - - while (timeLimitUs > 0) { - useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs); - usleep(duration); - timeLimitUs -= duration; - - environment->catEvents(&events); - if (events.size() >= nEventLimit) { - break; - } - ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs, - (int)(nEventLimit - events.size())); - } - - if (changeCollection) { - environment->setCollection(false); - } - return events; -} - -void SensorsHidlTestBase::assertTypeMatchStringType(SensorType type, - const hidl_string& stringType) { - if (type >= SensorType::DEVICE_PRIVATE_BASE) { - return; - } - - switch (type) { -#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \ - case SensorType::type: \ - ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \ - break; - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE); - CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE); - default: - FAIL() << "Type " << static_cast(type) - << " in android defined range is not checked, " - << "stringType = " << stringType; -#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE - } -} - -void SensorsHidlTestBase::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) { - if (type >= SensorType::DEVICE_PRIVATE_BASE) { - return; - } - - SensorFlagBits expected = expectedReportModeForType(type); - - ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode) - << "reportMode=" << static_cast(reportMode) - << "expected=" << static_cast(expected); -} - -void SensorsHidlTestBase::assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay, - SensorFlagBits reportMode) { - switch (reportMode) { - case SensorFlagBits::CONTINUOUS_MODE: - ASSERT_LT(0, minDelay); - ASSERT_LE(0, maxDelay); - break; - case SensorFlagBits::ON_CHANGE_MODE: - ASSERT_LE(0, minDelay); - ASSERT_LE(0, maxDelay); - break; - case SensorFlagBits::ONE_SHOT_MODE: - ASSERT_EQ(-1, minDelay); - ASSERT_EQ(0, maxDelay); - break; - case SensorFlagBits::SPECIAL_REPORTING_MODE: - // do not enforce anything for special reporting mode - break; - default: - FAIL() << "Report mode " << static_cast(reportMode) << " not checked"; - } -} - -// return -1 means no expectation for this type -SensorFlagBits SensorsHidlTestBase::expectedReportModeForType(SensorType type) { - switch (type) { - case SensorType::ACCELEROMETER: - case SensorType::ACCELEROMETER_UNCALIBRATED: - case SensorType::GYROSCOPE: - case SensorType::MAGNETIC_FIELD: - case SensorType::ORIENTATION: - case SensorType::PRESSURE: - case SensorType::TEMPERATURE: - case SensorType::GRAVITY: - case SensorType::LINEAR_ACCELERATION: - case SensorType::ROTATION_VECTOR: - case SensorType::MAGNETIC_FIELD_UNCALIBRATED: - case SensorType::GAME_ROTATION_VECTOR: - case SensorType::GYROSCOPE_UNCALIBRATED: - case SensorType::GEOMAGNETIC_ROTATION_VECTOR: - case SensorType::POSE_6DOF: - case SensorType::HEART_BEAT: - return SensorFlagBits::CONTINUOUS_MODE; - - case SensorType::LIGHT: - case SensorType::PROXIMITY: - case SensorType::RELATIVE_HUMIDITY: - case SensorType::AMBIENT_TEMPERATURE: - case SensorType::HEART_RATE: - case SensorType::DEVICE_ORIENTATION: - case SensorType::STEP_COUNTER: - case SensorType::LOW_LATENCY_OFFBODY_DETECT: - return SensorFlagBits::ON_CHANGE_MODE; - - case SensorType::SIGNIFICANT_MOTION: - case SensorType::WAKE_GESTURE: - case SensorType::GLANCE_GESTURE: - case SensorType::PICK_UP_GESTURE: - case SensorType::MOTION_DETECT: - case SensorType::STATIONARY_DETECT: - return SensorFlagBits::ONE_SHOT_MODE; - - case SensorType::STEP_DETECTOR: - case SensorType::TILT_DETECTOR: - case SensorType::WRIST_TILT_GESTURE: - case SensorType::DYNAMIC_SENSOR_META: - return SensorFlagBits::SPECIAL_REPORTING_MODE; - - default: - ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type); - return (SensorFlagBits)-1; - } -} - -bool SensorsHidlTestBase::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) { - unsigned int r = static_cast(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >> - static_cast(SensorFlagShift::DIRECT_REPORT); - return r >= static_cast(rate); -} - -bool SensorsHidlTestBase::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) { - switch (type) { - case SharedMemType::ASHMEM: - return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0; - case SharedMemType::GRALLOC: - return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0; - default: - return false; - } -} - -void SensorsHidlTestBase::testDirectReportOperation(SensorType type, SharedMemType memType, - RateLevel rate, - const SensorEventsChecker& checker) { - constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); - constexpr size_t kNEvent = 4096; - constexpr size_t kMemSize = kEventSize * kNEvent; - - constexpr float kNormalNominal = 50; - constexpr float kFastNominal = 200; - constexpr float kVeryFastNominal = 800; - - constexpr float kNominalTestTimeSec = 1.f; - constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f; // 0.5 second for initialization - - SensorInfo sensor = defaultSensorByType(type); - - if (!isValidType(sensor.type)) { - // no default sensor of this type - return; - } - - if (!isDirectReportRateSupported(sensor, rate)) { - return; - } - - if (!isDirectChannelTypeSupported(sensor, memType)) { - return; - } - - std::unique_ptr mem( - SensorsTestSharedMemory::create(memType, kMemSize)); - ASSERT_NE(mem, nullptr); - - char* buffer = mem->getBuffer(); - // fill memory with data - for (size_t i = 0; i < kMemSize; ++i) { - buffer[i] = '\xcc'; - } - - int32_t channelHandle; - registerDirectChannel(mem->getSharedMemInfo(), - [&channelHandle](auto result, auto channelHandle_) { - ASSERT_EQ(result, Result::OK); - channelHandle = channelHandle_; - }); - - // check memory is zeroed - for (size_t i = 0; i < kMemSize; ++i) { - ASSERT_EQ(buffer[i], '\0'); - } - - int32_t eventToken; - configDirectReport(sensor.sensorHandle, channelHandle, rate, - [&eventToken](auto result, auto token) { - ASSERT_EQ(result, Result::OK); - eventToken = token; - }); - - usleep(static_cast(kMaxTestTimeSec * 1e6f)); - auto events = mem->parseEvents(); - - // find norminal rate - float nominalFreq = 0.f; - switch (rate) { - case RateLevel::NORMAL: - nominalFreq = kNormalNominal; - break; - case RateLevel::FAST: - nominalFreq = kFastNominal; - break; - case RateLevel::VERY_FAST: - nominalFreq = kVeryFastNominal; - break; - case RateLevel::STOP: - FAIL(); - } - - // allowed to be between 55% and 220% of nominal freq - ASSERT_GT(events.size(), static_cast(nominalFreq * 0.55f * kNominalTestTimeSec)); - ASSERT_LT(events.size(), static_cast(nominalFreq * 2.2f * kMaxTestTimeSec)); - - int64_t lastTimestamp = 0; - bool typeErrorReported = false; - bool tokenErrorReported = false; - bool timestampErrorReported = false; - std::vector sensorEvents; - for (auto& e : events) { - if (!tokenErrorReported) { - EXPECT_EQ(eventToken, e.sensorHandle) - << (tokenErrorReported = true, - "Event token does not match that retured from configDirectReport"); - } - - if (isMetaSensorType(e.sensorType)) { - continue; - } - sensorEvents.push_back(e); - - if (!typeErrorReported) { - EXPECT_EQ(type, e.sensorType) - << (typeErrorReported = true, - "Type in event does not match type of sensor registered."); - } - if (!timestampErrorReported) { - EXPECT_GT(e.timestamp, lastTimestamp) - << (timestampErrorReported = true, "Timestamp not monotonically increasing"); - } - lastTimestamp = e.timestamp; - } - - std::string s; - EXPECT_TRUE(checker.check(sensorEvents, &s)) << s; - - // stop sensor and unregister channel - configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP, - [](auto result, auto) { EXPECT_EQ(result, Result::OK); }); - EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK); -} - -void SensorsHidlTestBase::testStreamingOperation(SensorType type, - std::chrono::nanoseconds samplingPeriod, - std::chrono::seconds duration, - const SensorEventsChecker& checker) { - std::vector events; - std::vector sensorEvents; - - const int64_t samplingPeriodInNs = samplingPeriod.count(); - const int64_t batchingPeriodInNs = 0; // no batching - const useconds_t minTimeUs = std::chrono::microseconds(duration).count(); - const size_t minNEvent = duration / samplingPeriod; - - SensorInfo sensor = defaultSensorByType(type); - - if (!isValidType(sensor.type)) { - // no default sensor of this type - return; - } - - if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) { - // rate not supported - return; - } - - int32_t handle = sensor.sensorHandle; - - ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK); - ASSERT_EQ(activate(handle, 1), Result::OK); - events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/); - ASSERT_EQ(activate(handle, 0), Result::OK); - - ALOGI("Collected %zu samples", events.size()); - - ASSERT_GT(events.size(), 0u); - - bool handleMismatchReported = false; - bool metaSensorTypeErrorReported = false; - for (auto& e : events) { - if (e.sensorType == type) { - // avoid generating hundreds of error - if (!handleMismatchReported) { - EXPECT_EQ(e.sensorHandle, handle) - << (handleMismatchReported = true, - "Event of the same type must come from the sensor registered"); - } - sensorEvents.push_back(e); - } else { - // avoid generating hundreds of error - if (!metaSensorTypeErrorReported) { - EXPECT_TRUE(isMetaSensorType(e.sensorType)) - << (metaSensorTypeErrorReported = true, - "Only meta types are allowed besides the type registered"); - } - } - } - - std::string s; - EXPECT_TRUE(checker.check(sensorEvents, &s)) << s; - - EXPECT_GE(sensorEvents.size(), - minNEvent / 2); // make sure returned events are not all meta -} - -void SensorsHidlTestBase::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) { - std::vector events1, events2; - - constexpr int64_t batchingPeriodInNs = 0; // no batching - constexpr int64_t collectionTimeoutUs = 60000000; // 60s - constexpr size_t minNEvent = 50; - - SensorInfo sensor = defaultSensorByType(type); - - if (!isValidType(sensor.type)) { - // no default sensor of this type - return; - } - - int32_t handle = sensor.sensorHandle; - int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll; - int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll; - - if (minSamplingPeriodInNs == maxSamplingPeriodInNs) { - // only support single rate - return; - } - - int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs; - int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs; - - // first collection - ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK); - ASSERT_EQ(activate(handle, 1), Result::OK); - - usleep(500000); // sleep 0.5 sec to wait for change rate to happen - events1 = collectEvents(collectionTimeoutUs, minNEvent); - - // second collection, without stop sensor - ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK); - - usleep(500000); // sleep 0.5 sec to wait for change rate to happen - events2 = collectEvents(collectionTimeoutUs, minNEvent); - - // end of collection, stop sensor - ASSERT_EQ(activate(handle, 0), Result::OK); - - ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size()); - - ASSERT_GT(events1.size(), 0u); - ASSERT_GT(events2.size(), 0u); - - int64_t minDelayAverageInterval, maxDelayAverageInterval; - std::vector& minDelayEvents(fastToSlow ? events1 : events2); - std::vector& maxDelayEvents(fastToSlow ? events2 : events1); - - size_t nEvent = 0; - int64_t prevTimestamp = -1; - int64_t timestampInterval = 0; - for (auto& e : minDelayEvents) { - if (e.sensorType == type) { - ASSERT_EQ(e.sensorHandle, handle); - if (prevTimestamp > 0) { - timestampInterval += e.timestamp - prevTimestamp; - } - prevTimestamp = e.timestamp; - ++nEvent; - } - } - ASSERT_GT(nEvent, 2u); - minDelayAverageInterval = timestampInterval / (nEvent - 1); - - nEvent = 0; - prevTimestamp = -1; - timestampInterval = 0; - for (auto& e : maxDelayEvents) { - if (e.sensorType == type) { - ASSERT_EQ(e.sensorHandle, handle); - if (prevTimestamp > 0) { - timestampInterval += e.timestamp - prevTimestamp; - } - prevTimestamp = e.timestamp; - ++nEvent; - } - } - ASSERT_GT(nEvent, 2u); - maxDelayAverageInterval = timestampInterval / (nEvent - 1); - - // change of rate is significant. - ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval, - maxDelayAverageInterval); - EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10); - - // fastest rate sampling time is close to spec - EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs), - minSamplingPeriodInNs / 10); - - // slowest rate sampling time is close to spec - EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs), - maxSamplingPeriodInNs / 10); -} - -void SensorsHidlTestBase::testBatchingOperation(SensorType type) { - std::vector events; - - constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000; - constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000; - - SensorInfo sensor = defaultSensorByType(type); - - if (!isValidType(sensor.type)) { - // no default sensor of this type - return; - } - - int32_t handle = sensor.sensorHandle; - int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll; - uint32_t minFifoCount = sensor.fifoReservedEventCount; - int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs; - - if (batchingPeriodInNs < oneSecondInNs) { - // batching size too small to test reliably - return; - } - - batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs); - - ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000)); - - int64_t allowedBatchDeliverTimeNs = std::max(oneSecondInNs, batchingPeriodInNs / 10); - - ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK); - ASSERT_EQ(activate(handle, 1), Result::OK); - - usleep(500000); // sleep 0.5 sec to wait for initialization - ASSERT_EQ(flush(handle), Result::OK); - - // wait for 80% of the reserved batching period - // there should not be any significant amount of events - // since collection is not enabled all events will go down the drain - usleep(batchingPeriodInNs / 1000 * 8 / 10); - - getEnvironment()->setCollection(true); - // clean existing collections - collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/, - false /*change collection*/); - - // 0.8 + 0.2 times the batching period - usleep(batchingPeriodInNs / 1000 * 8 / 10); - ASSERT_EQ(flush(handle), Result::OK); - - // plus some time for the event to deliver - events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount, - false /*clearBeforeStart*/, false /*change collection*/); - - getEnvironment()->setCollection(false); - ASSERT_EQ(activate(handle, 0), Result::OK); - - size_t nEvent = 0; - for (auto& e : events) { - if (e.sensorType == type && e.sensorHandle == handle) { - ++nEvent; - } - } - - // at least reach 90% of advertised capacity - ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10)); -} diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp deleted file mode 100644 index 3b068bd5c5..0000000000 --- a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2018 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 "SensorsTestSharedMemory.h" - -#include - -#include -#include - -using namespace ::android::hardware::sensors::V1_0; - -SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const { - SharedMemInfo mem = {.type = mType, - .format = SharedMemFormat::SENSORS_EVENT, - .size = static_cast(mSize), - .memoryHandle = mNativeHandle}; - return mem; -} - -char* SensorsTestSharedMemory::getBuffer() const { - return mBuffer; -} - -size_t SensorsTestSharedMemory::getSize() const { - return mSize; -} - -std::vector SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const { - constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); - constexpr size_t kOffsetSize = static_cast(SensorsEventFormatOffset::SIZE_FIELD); - constexpr size_t kOffsetToken = static_cast(SensorsEventFormatOffset::REPORT_TOKEN); - constexpr size_t kOffsetType = static_cast(SensorsEventFormatOffset::SENSOR_TYPE); - constexpr size_t kOffsetAtomicCounter = - static_cast(SensorsEventFormatOffset::ATOMIC_COUNTER); - constexpr size_t kOffsetTimestamp = static_cast(SensorsEventFormatOffset::TIMESTAMP); - constexpr size_t kOffsetData = static_cast(SensorsEventFormatOffset::DATA); - - std::vector events; - std::vector data(16); - - while (offset + kEventSize <= mSize) { - int64_t atomicCounter = - *reinterpret_cast(mBuffer + offset + kOffsetAtomicCounter); - if (atomicCounter <= lastCounter) { - ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, - lastCounter); - break; - } - - int32_t size = *reinterpret_cast(mBuffer + offset + kOffsetSize); - if (size != kEventSize) { - // unknown error, events parsed may be wrong, remove all - events.clear(); - break; - } - - int32_t token = *reinterpret_cast(mBuffer + offset + kOffsetToken); - int32_t type = *reinterpret_cast(mBuffer + offset + kOffsetType); - int64_t timestamp = *reinterpret_cast(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 = static_cast(type), - }; - event.u.data = android::hardware::hidl_array( - reinterpret_cast(mBuffer + offset + kOffsetData)); - - events.push_back(event); - - lastCounter = atomicCounter; - offset += kEventSize; - } - - return events; -} - -SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size) - : mType(type), mSize(0), mBuffer(nullptr) { - native_handle_t* handle = nullptr; - char* buffer = nullptr; - switch (type) { - case SharedMemType::ASHMEM: { - int fd; - handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/); - if (handle != nullptr) { - handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size); - if (handle->data[0] > 0) { - // memory is pinned by default - buffer = static_cast( - ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); - if (buffer != reinterpret_cast(MAP_FAILED)) { - break; - } - ::native_handle_close(handle); - } - ::native_handle_delete(handle); - handle = nullptr; - } - break; - } - case SharedMemType::GRALLOC: { - mGrallocWrapper = std::make_unique<::android::GrallocWrapper>(); - if (!mGrallocWrapper->isInitialized()) { - break; - } - - std::pair buf = mGrallocWrapper->allocate(size); - handle = buf.first; - buffer = static_cast(buf.second); - break; - } - default: - break; - } - - if (buffer != nullptr) { - mNativeHandle = handle; - mSize = size; - mBuffer = buffer; - } -} - -SensorsTestSharedMemory::~SensorsTestSharedMemory() { - switch (mType) { - case SharedMemType::ASHMEM: { - if (mSize != 0) { - ::munmap(mBuffer, mSize); - mBuffer = nullptr; - - ::native_handle_close(mNativeHandle); - ::native_handle_delete(mNativeHandle); - - mNativeHandle = nullptr; - mSize = 0; - } - break; - } - case SharedMemType::GRALLOC: { - if (mSize != 0) { - mGrallocWrapper->freeBuffer(mNativeHandle); - mNativeHandle = nullptr; - mSize = 0; - } - break; - } - default: { - if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) { - ALOGE( - "SensorsTestSharedMemory %p not properly destructed: " - "type %d, native handle %p, size %zu, buffer %p", - this, static_cast(mType), mNativeHandle, mSize, mBuffer); - } - break; - } - } -} - -SensorsTestSharedMemory* SensorsTestSharedMemory::create(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 SensorsTestSharedMemory(type, size); - if (m->mSize != size || m->mBuffer == nullptr) { - delete m; - m = nullptr; - } - return m; -} diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h index b5daccc987..d6d3227be5 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h @@ -17,26 +17,26 @@ #ifndef ANDROID_SENSOR_EVENTS_CHECKER_H #define ANDROID_SENSOR_EVENTS_CHECKER_H -#include - #include +template class SensorEventsChecker { - public: - using Event = ::android::hardware::sensors::V1_0::Event; - virtual bool check(const std::vector& events, std::string* out) const = 0; + public: + virtual bool check(const std::vector& events, std::string* out) const = 0; virtual ~SensorEventsChecker() {} }; -class NullChecker : public SensorEventsChecker { - public: - virtual bool check(const std::vector&, std::string*) const { return true; } +template +class NullChecker : public SensorEventsChecker { + public: + virtual bool check(const std::vector&, std::string*) const { return true; } }; -class SensorEventPerEventChecker : public SensorEventsChecker { - public: - virtual bool checkEvent(const Event& event, std::string* out) const = 0; - virtual bool check(const std::vector& events, std::string* out) const { +template +class SensorEventPerEventChecker : public SensorEventsChecker { + public: + virtual bool checkEvent(const EventType& event, std::string* out) const = 0; + virtual bool check(const std::vector& events, std::string* out) const { for (const auto& e : events) { if (!checkEvent(e, out)) { return false; @@ -46,14 +46,15 @@ class SensorEventPerEventChecker : public SensorEventsChecker { } }; -class Vec3NormChecker : public SensorEventPerEventChecker { - public: +template +class Vec3NormChecker : public SensorEventPerEventChecker { + public: Vec3NormChecker(float min, float max) : mLowerLimit(min), mUpperLimit(max) {} - static Vec3NormChecker byNominal(float nominal, float allowedError) { - return Vec3NormChecker(nominal - allowedError, nominal + allowedError); + static Vec3NormChecker byNominal(float nominal, float allowedError) { + return Vec3NormChecker(nominal - allowedError, nominal + allowedError); } - virtual bool checkEvent(const Event& event, std::string* out) const { + virtual bool checkEvent(const EventType& event, std::string* out) const { android::hardware::sensors::V1_0::Vec3 v = event.u.vec3; float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z); if (norm < mLowerLimit || norm > mUpperLimit) { 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 dbc9392ade..781427d827 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h @@ -17,7 +17,6 @@ #ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H #define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H -#include #include #include @@ -26,27 +25,59 @@ #include #include +template class IEventCallback { - public: + public: virtual ~IEventCallback() = default; - virtual void onEvent(const ::android::hardware::sensors::V1_0::Event& event) = 0; + virtual void onEvent(const Event& event) = 0; }; +template class SensorsHidlEnvironmentBase { public: - using Event = ::android::hardware::sensors::V1_0::Event; - virtual void HidlSetUp(); - virtual void HidlTearDown(); + virtual void HidlSetUp() { + ASSERT_TRUE(resetHal()) << "could not get hidl service"; + + mCollectionEnabled = false; + startPollingThread(); + + // In case framework just stopped for test and there is sensor events in the pipe, + // wait some time for those events to be cleared to avoid them messing up the test. + std::this_thread::sleep_for(std::chrono::seconds(3)); + } + + virtual void HidlTearDown() { + mStopThread = true; + if (mPollThread.joinable()) { + mPollThread.join(); + } + } // Get and clear all events collected so far (like "cat" shell command). // If output is nullptr, it clears all collected events. - void catEvents(std::vector* output); + void catEvents(std::vector* output) { + std::lock_guard lock(mEventsMutex); + if (output) { + output->insert(output->end(), mEvents.begin(), mEvents.end()); + } + mEvents.clear(); + } // set sensor event collection status - void setCollection(bool enable); + void setCollection(bool enable) { + std::lock_guard lock(mEventsMutex); + mCollectionEnabled = enable; + } - void registerCallback(IEventCallback* callback); - void unregisterCallback(); + void registerCallback(IEventCallback* callback) { + std::lock_guard lock(mEventsMutex); + mCallback = callback; + } + + void unregisterCallback() { + std::lock_guard lock(mEventsMutex); + mCallback = nullptr; + } protected: SensorsHidlEnvironmentBase(const std::string& service_name) @@ -55,7 +86,16 @@ class SensorsHidlEnvironmentBase { } virtual ~SensorsHidlEnvironmentBase(){}; - void addEvent(const Event& ev); + void addEvent(const Event& ev) { + std::lock_guard lock(mEventsMutex); + if (mCollectionEnabled) { + mEvents.push_back(ev); + } + + if (mCallback != nullptr) { + mCallback->onEvent(ev); + } + } virtual void startPollingThread() = 0; virtual bool resetHal() = 0; @@ -67,9 +107,9 @@ class SensorsHidlEnvironmentBase { std::vector mEvents; std::mutex mEventsMutex; - IEventCallback* mCallback; + IEventCallback* mCallback; - GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase); + GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase); }; #endif // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H \ No newline at end of file diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h index 54e899b900..03bec87d0c 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h @@ -19,11 +19,15 @@ #include "sensors-vts-utils/SensorEventsChecker.h" #include "sensors-vts-utils/SensorsHidlEnvironmentBase.h" +#include "sensors-vts-utils/SensorsTestSharedMemory.h" #include #include #include +#include +#include +#include #include #include @@ -34,19 +38,130 @@ using ::android::hardware::Void; using ::android::sp; using ::android::hardware::hidl_string; -using ::android::hardware::sensors::V1_0::Event; -using ::android::hardware::sensors::V1_0::ISensors; using ::android::hardware::sensors::V1_0::RateLevel; using ::android::hardware::sensors::V1_0::Result; using ::android::hardware::sensors::V1_0::SensorFlagBits; -using ::android::hardware::sensors::V1_0::SensorInfo; -using ::android::hardware::sensors::V1_0::SensorType; +using ::android::hardware::sensors::V1_0::SensorFlagShift; +using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset; using ::android::hardware::sensors::V1_0::SharedMemInfo; using ::android::hardware::sensors::V1_0::SharedMemType; +template +static void assertTypeMatchStringType(SensorTypeT type, const hidl_string& stringType) { + if (type >= SensorTypeT::DEVICE_PRIVATE_BASE) { + return; + } + + switch (type) { +#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \ + case SensorTypeT::type: \ + ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \ + break; + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE); + CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE); + default: + FAIL() << "Type " << static_cast(type) + << " in android defined range is not checked, " + << "stringType = " << stringType; +#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE + } +} + +template +static SensorFlagBits expectedReportModeForType(SensorTypeT type) { + switch (type) { + case SensorTypeT::ACCELEROMETER: + case SensorTypeT::ACCELEROMETER_UNCALIBRATED: + case SensorTypeT::GYROSCOPE: + case SensorTypeT::MAGNETIC_FIELD: + case SensorTypeT::ORIENTATION: + case SensorTypeT::PRESSURE: + case SensorTypeT::TEMPERATURE: + case SensorTypeT::GRAVITY: + case SensorTypeT::LINEAR_ACCELERATION: + case SensorTypeT::ROTATION_VECTOR: + case SensorTypeT::MAGNETIC_FIELD_UNCALIBRATED: + case SensorTypeT::GAME_ROTATION_VECTOR: + case SensorTypeT::GYROSCOPE_UNCALIBRATED: + case SensorTypeT::GEOMAGNETIC_ROTATION_VECTOR: + case SensorTypeT::POSE_6DOF: + case SensorTypeT::HEART_BEAT: + return SensorFlagBits::CONTINUOUS_MODE; + + case SensorTypeT::LIGHT: + case SensorTypeT::PROXIMITY: + case SensorTypeT::RELATIVE_HUMIDITY: + case SensorTypeT::AMBIENT_TEMPERATURE: + case SensorTypeT::HEART_RATE: + case SensorTypeT::DEVICE_ORIENTATION: + case SensorTypeT::STEP_COUNTER: + case SensorTypeT::LOW_LATENCY_OFFBODY_DETECT: + return SensorFlagBits::ON_CHANGE_MODE; + + case SensorTypeT::SIGNIFICANT_MOTION: + case SensorTypeT::WAKE_GESTURE: + case SensorTypeT::GLANCE_GESTURE: + case SensorTypeT::PICK_UP_GESTURE: + case SensorTypeT::MOTION_DETECT: + case SensorTypeT::STATIONARY_DETECT: + return SensorFlagBits::ONE_SHOT_MODE; + + case SensorTypeT::STEP_DETECTOR: + case SensorTypeT::TILT_DETECTOR: + case SensorTypeT::WRIST_TILT_GESTURE: + case SensorTypeT::DYNAMIC_SENSOR_META: + return SensorFlagBits::SPECIAL_REPORTING_MODE; + + default: + ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type); + return (SensorFlagBits)-1; + } +} + +template class SensorsHidlTestBase : public testing::TestWithParam { public: - virtual SensorsHidlEnvironmentBase* getEnvironment() = 0; + using ISensors = ::android::hardware::sensors::V1_0::ISensors; + + SensorsHidlTestBase() + : mAccelNormChecker(Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/)), + mGyroNormChecker(Vec3NormChecker::byNominal(0.f, 0.1f /*rad/s*/)) {} + + virtual SensorsHidlEnvironmentBase* getEnvironment() = 0; + virtual void SetUp() override {} virtual void TearDown() override { @@ -66,16 +181,13 @@ class SensorsHidlTestBase : public testing::TestWithParam { } // implementation wrapper - virtual SensorInfo defaultSensorByType(SensorType type) = 0; + virtual SensorInfoType defaultSensorByType(SensorTypeVersion type) = 0; virtual Return getSensorsList(ISensors::getSensorsList_cb _hidl_cb) = 0; - + virtual Return injectSensorData(const EventType& event) = 0; virtual Return activate(int32_t sensorHandle, bool enabled) = 0; - virtual Return batch(int32_t sensorHandle, int64_t samplingPeriodNs, int64_t maxReportLatencyNs) = 0; - virtual Return flush(int32_t sensorHandle) = 0; - virtual Return injectSensorData(const Event& event) = 0; virtual Return registerDirectChannel(const SharedMemInfo& mem, ISensors::registerDirectChannel_cb _hidl_cb) = 0; virtual Return unregisterDirectChannel(int32_t channelHandle) = 0; @@ -83,12 +195,395 @@ class SensorsHidlTestBase : public testing::TestWithParam { RateLevel rate, ISensors::configDirectReport_cb _hidl_cb) = 0; - std::vector collectEvents(useconds_t timeLimitUs, size_t nEventLimit, - bool clearBeforeStart = true, bool changeCollection = true); - static std::vector collectEvents(useconds_t timeLimitUs, size_t nEventLimit, - SensorsHidlEnvironmentBase* environment, - bool clearBeforeStart = true, - bool changeCollection = true); + std::vector collectEvents(useconds_t timeLimitUs, size_t nEventLimit, + bool clearBeforeStart = true, + bool changeCollection = true) { + return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart, + changeCollection); + } + + std::vector collectEvents(useconds_t timeLimitUs, size_t nEventLimit, + SensorsHidlEnvironmentBase* environment, + bool clearBeforeStart = true, + bool changeCollection = true) { + std::vector events; + constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000; // granularity 100 ms + + ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs, + clearBeforeStart); + + if (changeCollection) { + environment->setCollection(true); + } + if (clearBeforeStart) { + environment->catEvents(nullptr); + } + + while (timeLimitUs > 0) { + useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs); + usleep(duration); + timeLimitUs -= duration; + + environment->catEvents(&events); + if (events.size() >= nEventLimit) { + break; + } + ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs, + (int)(nEventLimit - events.size())); + } + + if (changeCollection) { + environment->setCollection(false); + } + return events; + } + + void testStreamingOperation(SensorTypeVersion type, std::chrono::nanoseconds samplingPeriod, + std::chrono::seconds duration, + const SensorEventsChecker& checker) { + std::vector events; + std::vector sensorEvents; + + const int64_t samplingPeriodInNs = samplingPeriod.count(); + const int64_t batchingPeriodInNs = 0; // no batching + const useconds_t minTimeUs = std::chrono::microseconds(duration).count(); + const size_t minNEvent = duration / samplingPeriod; + + SensorInfoType sensor = defaultSensorByType(type); + + if (!isValidType(sensor.type)) { + // no default sensor of this type + return; + } + + if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) { + // rate not supported + return; + } + + int32_t handle = sensor.sensorHandle; + + ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK); + ASSERT_EQ(activate(handle, 1), Result::OK); + events = collectEvents(minTimeUs, minNEvent, getEnvironment(), true /*clearBeforeStart*/); + ASSERT_EQ(activate(handle, 0), Result::OK); + + ALOGI("Collected %zu samples", events.size()); + + ASSERT_GT(events.size(), 0u); + + bool handleMismatchReported = false; + bool metaSensorTypeErrorReported = false; + for (auto& e : events) { + if (e.sensorType == type) { + // avoid generating hundreds of error + if (!handleMismatchReported) { + EXPECT_EQ(e.sensorHandle, handle) + << (handleMismatchReported = true, + "Event of the same type must come from the sensor registered"); + } + sensorEvents.push_back(e); + } else { + // avoid generating hundreds of error + if (!metaSensorTypeErrorReported) { + EXPECT_TRUE(isMetaSensorType(e.sensorType)) + << (metaSensorTypeErrorReported = true, + "Only meta types are allowed besides the type registered"); + } + } + } + + std::string s; + EXPECT_TRUE(checker.check(sensorEvents, &s)) << s; + + EXPECT_GE(sensorEvents.size(), + minNEvent / 2); // make sure returned events are not all meta + } + + void testSamplingRateHotSwitchOperation(SensorTypeVersion type, bool fastToSlow = true) { + std::vector events1, events2; + + constexpr int64_t batchingPeriodInNs = 0; // no batching + constexpr int64_t collectionTimeoutUs = 60000000; // 60s + constexpr size_t minNEvent = 50; + + SensorInfoType sensor = defaultSensorByType(type); + + if (!isValidType(sensor.type)) { + // no default sensor of this type + return; + } + + int32_t handle = sensor.sensorHandle; + int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll; + int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll; + + if (minSamplingPeriodInNs == maxSamplingPeriodInNs) { + // only support single rate + return; + } + + int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs; + int64_t secondCollectionPeriod = + !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs; + + // first collection + ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK); + ASSERT_EQ(activate(handle, 1), Result::OK); + + usleep(500000); // sleep 0.5 sec to wait for change rate to happen + events1 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment()); + + // second collection, without stop sensor + ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK); + + usleep(500000); // sleep 0.5 sec to wait for change rate to happen + events2 = collectEvents(collectionTimeoutUs, minNEvent, getEnvironment()); + + // end of collection, stop sensor + ASSERT_EQ(activate(handle, 0), Result::OK); + + ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size()); + + ASSERT_GT(events1.size(), 0u); + ASSERT_GT(events2.size(), 0u); + + int64_t minDelayAverageInterval, maxDelayAverageInterval; + std::vector& minDelayEvents(fastToSlow ? events1 : events2); + std::vector& maxDelayEvents(fastToSlow ? events2 : events1); + + size_t nEvent = 0; + int64_t prevTimestamp = -1; + int64_t timestampInterval = 0; + for (auto& e : minDelayEvents) { + if (e.sensorType == type) { + ASSERT_EQ(e.sensorHandle, handle); + if (prevTimestamp > 0) { + timestampInterval += e.timestamp - prevTimestamp; + } + prevTimestamp = e.timestamp; + ++nEvent; + } + } + ASSERT_GT(nEvent, 2u); + minDelayAverageInterval = timestampInterval / (nEvent - 1); + + nEvent = 0; + prevTimestamp = -1; + timestampInterval = 0; + for (auto& e : maxDelayEvents) { + if (e.sensorType == type) { + ASSERT_EQ(e.sensorHandle, handle); + if (prevTimestamp > 0) { + timestampInterval += e.timestamp - prevTimestamp; + } + prevTimestamp = e.timestamp; + ++nEvent; + } + } + ASSERT_GT(nEvent, 2u); + maxDelayAverageInterval = timestampInterval / (nEvent - 1); + + // change of rate is significant. + ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval, + maxDelayAverageInterval); + EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), + minDelayAverageInterval / 10); + + // fastest rate sampling time is close to spec + EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs), + minSamplingPeriodInNs / 10); + + // slowest rate sampling time is close to spec + EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs), + maxSamplingPeriodInNs / 10); + } + + void testBatchingOperation(SensorTypeVersion type) { + std::vector events; + + constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000; + constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000; + + SensorInfoType sensor = defaultSensorByType(type); + + if (!isValidType(sensor.type)) { + // no default sensor of this type + return; + } + + int32_t handle = sensor.sensorHandle; + int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll; + uint32_t minFifoCount = sensor.fifoReservedEventCount; + int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs; + + if (batchingPeriodInNs < oneSecondInNs) { + // batching size too small to test reliably + return; + } + + batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs); + + ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000)); + + int64_t allowedBatchDeliverTimeNs = std::max(oneSecondInNs, batchingPeriodInNs / 10); + + ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK); + ASSERT_EQ(activate(handle, 1), Result::OK); + + usleep(500000); // sleep 0.5 sec to wait for initialization + ASSERT_EQ(flush(handle), Result::OK); + + // wait for 80% of the reserved batching period + // there should not be any significant amount of events + // since collection is not enabled all events will go down the drain + usleep(batchingPeriodInNs / 1000 * 8 / 10); + + getEnvironment()->setCollection(true); + // clean existing collections + collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/, + false /*change collection*/); + + // 0.8 + 0.2 times the batching period + usleep(batchingPeriodInNs / 1000 * 8 / 10); + ASSERT_EQ(flush(handle), Result::OK); + + // plus some time for the event to deliver + events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount, + false /*clearBeforeStart*/, false /*change collection*/); + + getEnvironment()->setCollection(false); + ASSERT_EQ(activate(handle, 0), Result::OK); + + size_t nEvent = 0; + for (auto& e : events) { + if (e.sensorType == type && e.sensorHandle == handle) { + ++nEvent; + } + } + + // at least reach 90% of advertised capacity + ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10)); + } + + void testDirectReportOperation(SensorTypeVersion type, SharedMemType memType, RateLevel rate, + const SensorEventsChecker& checker) { + constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); + constexpr size_t kNEvent = 4096; + constexpr size_t kMemSize = kEventSize * kNEvent; + + constexpr float kNormalNominal = 50; + constexpr float kFastNominal = 200; + constexpr float kVeryFastNominal = 800; + + constexpr float kNominalTestTimeSec = 1.f; + constexpr float kMaxTestTimeSec = + kNominalTestTimeSec + 0.5f; // 0.5 second for initialization + + SensorInfoType sensor = defaultSensorByType(type); + + if (!isValidType(sensor.type)) { + // no default sensor of this type + return; + } + + if (!isDirectReportRateSupported(sensor, rate)) { + return; + } + + if (!isDirectChannelTypeSupported(sensor, memType)) { + return; + } + + std::unique_ptr> mem( + SensorsTestSharedMemory::create(memType, kMemSize)); + ASSERT_NE(mem, nullptr); + + char* buffer = mem->getBuffer(); + // fill memory with data + for (size_t i = 0; i < kMemSize; ++i) { + buffer[i] = '\xcc'; + } + + int32_t channelHandle; + registerDirectChannel(mem->getSharedMemInfo(), + [&channelHandle](auto result, auto channelHandle_) { + ASSERT_EQ(result, Result::OK); + channelHandle = channelHandle_; + }); + + // check memory is zeroed + for (size_t i = 0; i < kMemSize; ++i) { + ASSERT_EQ(buffer[i], '\0'); + } + + int32_t eventToken; + configDirectReport(sensor.sensorHandle, channelHandle, rate, + [&eventToken](auto result, auto token) { + ASSERT_EQ(result, Result::OK); + eventToken = token; + }); + + usleep(static_cast(kMaxTestTimeSec * 1e6f)); + auto events = mem->parseEvents(); + + // find norminal rate + float nominalFreq = 0.f; + switch (rate) { + case RateLevel::NORMAL: + nominalFreq = kNormalNominal; + break; + case RateLevel::FAST: + nominalFreq = kFastNominal; + break; + case RateLevel::VERY_FAST: + nominalFreq = kVeryFastNominal; + break; + case RateLevel::STOP: + FAIL(); + } + + // allowed to be between 55% and 220% of nominal freq + ASSERT_GT(events.size(), static_cast(nominalFreq * 0.55f * kNominalTestTimeSec)); + ASSERT_LT(events.size(), static_cast(nominalFreq * 2.2f * kMaxTestTimeSec)); + + int64_t lastTimestamp = 0; + bool typeErrorReported = false; + bool tokenErrorReported = false; + bool timestampErrorReported = false; + std::vector sensorEvents; + for (auto& e : events) { + if (!tokenErrorReported) { + EXPECT_EQ(eventToken, e.sensorHandle) + << (tokenErrorReported = true, + "Event token does not match that retured from configDirectReport"); + } + + if (isMetaSensorType(e.sensorType)) { + continue; + } + sensorEvents.push_back(e); + + if (!typeErrorReported) { + EXPECT_EQ(type, e.sensorType) + << (typeErrorReported = true, + "Type in event does not match type of sensor registered."); + } + if (!timestampErrorReported) { + EXPECT_GT(e.timestamp, lastTimestamp) << (timestampErrorReported = true, + "Timestamp not monotonically increasing"); + } + lastTimestamp = e.timestamp; + } + + std::string s; + EXPECT_TRUE(checker.check(sensorEvents, &s)) << s; + + // stop sensor and unregister channel + configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP, + [](auto result, auto) { EXPECT_EQ(result, Result::OK); }); + EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK); + } inline static SensorFlagBits extractReportMode(uint64_t flag) { return (SensorFlagBits)(flag & ((uint64_t)SensorFlagBits::CONTINUOUS_MODE | @@ -97,32 +592,71 @@ class SensorsHidlTestBase : public testing::TestWithParam { (uint64_t)SensorFlagBits::SPECIAL_REPORTING_MODE)); } - inline static bool isMetaSensorType(SensorType type) { - return (type == SensorType::META_DATA || type == SensorType::DYNAMIC_SENSOR_META || - type == SensorType::ADDITIONAL_INFO); + inline static bool isMetaSensorType(SensorTypeVersion type) { + return (type == SensorTypeVersion::META_DATA || + type == SensorTypeVersion::DYNAMIC_SENSOR_META || + type == SensorTypeVersion::ADDITIONAL_INFO); } - inline static bool isValidType(SensorType type) { return (int32_t)type > 0; } + inline static bool isValidType(SensorTypeVersion type) { return (int32_t)type > 0; } - void testStreamingOperation(SensorType type, std::chrono::nanoseconds samplingPeriod, - std::chrono::seconds duration, const SensorEventsChecker& checker); - void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true); - void testBatchingOperation(SensorType type); - void testDirectReportOperation(SensorType type, SharedMemType memType, RateLevel rate, - const SensorEventsChecker& checker); - - static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType); - static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode); static void assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay, - SensorFlagBits reportMode); - static SensorFlagBits expectedReportModeForType(SensorType type); - static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate); - static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type); + SensorFlagBits reportMode) { + switch (reportMode) { + case SensorFlagBits::CONTINUOUS_MODE: + ASSERT_LT(0, minDelay); + ASSERT_LE(0, maxDelay); + break; + case SensorFlagBits::ON_CHANGE_MODE: + ASSERT_LE(0, minDelay); + ASSERT_LE(0, maxDelay); + break; + case SensorFlagBits::ONE_SHOT_MODE: + ASSERT_EQ(-1, minDelay); + ASSERT_EQ(0, maxDelay); + break; + case SensorFlagBits::SPECIAL_REPORTING_MODE: + // do not enforce anything for special reporting mode + break; + default: + FAIL() << "Report mode " << static_cast(reportMode) << " not checked"; + } + } - protected: - // checkers - static const Vec3NormChecker sAccelNormChecker; - static const Vec3NormChecker sGyroNormChecker; + protected: + static void assertTypeMatchReportMode(SensorTypeVersion type, SensorFlagBits reportMode) { + if (type >= SensorTypeVersion::DEVICE_PRIVATE_BASE) { + return; + } + + SensorFlagBits expected = expectedReportModeForType(type); + + ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode) + << "reportMode=" << static_cast(reportMode) + << "expected=" << static_cast(expected); + } + + static bool isDirectReportRateSupported(SensorInfoType sensor, RateLevel rate) { + unsigned int r = + static_cast(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >> + static_cast(SensorFlagShift::DIRECT_REPORT); + return r >= static_cast(rate); + } + + static bool isDirectChannelTypeSupported(SensorInfoType sensor, SharedMemType type) { + switch (type) { + case SharedMemType::ASHMEM: + return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0; + case SharedMemType::GRALLOC: + return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0; + default: + return false; + } + } + + // Checkers + Vec3NormChecker mAccelNormChecker; + Vec3NormChecker mGyroNormChecker; // all sensors and direct channnels used std::unordered_set mSensorHandles; diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h index 002f42c112..39084a45e6 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h @@ -20,25 +20,177 @@ #include "GrallocWrapper.h" #include -#include +#include + +#include +#include #include +using namespace ::android::hardware::sensors::V1_0; + +template class SensorsTestSharedMemory { - using SharedMemType = ::android::hardware::sensors::V1_0::SharedMemType; - using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo; - using Event = ::android::hardware::sensors::V1_0::Event; + public: + static SensorsTestSharedMemory* create(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; + } - public: - static SensorsTestSharedMemory* create(SharedMemType type, size_t size); - SharedMemInfo getSharedMemInfo() const; - char* getBuffer() const; - size_t getSize() const; - std::vector parseEvents(int64_t lastCounter = -1, size_t offset = 0) const; - virtual ~SensorsTestSharedMemory(); + auto m = new SensorsTestSharedMemory(type, size); + if (m->mSize != size || m->mBuffer == nullptr) { + delete m; + m = nullptr; + } + return m; + } - private: - SensorsTestSharedMemory(SharedMemType type, size_t size); + SharedMemInfo getSharedMemInfo() const { + SharedMemInfo mem = {.type = mType, + .format = SharedMemFormat::SENSORS_EVENT, + .size = static_cast(mSize), + .memoryHandle = mNativeHandle}; + return mem; + } + char* getBuffer() const { return mBuffer; } + size_t getSize() const { return mSize; } + std::vector parseEvents(int64_t lastCounter = -1, size_t offset = 0) const { + constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); + constexpr size_t kOffsetSize = static_cast(SensorsEventFormatOffset::SIZE_FIELD); + constexpr size_t kOffsetToken = static_cast(SensorsEventFormatOffset::REPORT_TOKEN); + constexpr size_t kOffsetType = static_cast(SensorsEventFormatOffset::SENSOR_TYPE); + constexpr size_t kOffsetAtomicCounter = + static_cast(SensorsEventFormatOffset::ATOMIC_COUNTER); + constexpr size_t kOffsetTimestamp = + static_cast(SensorsEventFormatOffset::TIMESTAMP); + constexpr size_t kOffsetData = static_cast(SensorsEventFormatOffset::DATA); + + std::vector events; + std::vector data(16); + + while (offset + kEventSize <= mSize) { + int64_t atomicCounter = + *reinterpret_cast(mBuffer + offset + kOffsetAtomicCounter); + if (atomicCounter <= lastCounter) { + ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, + lastCounter); + break; + } + + int32_t size = *reinterpret_cast(mBuffer + offset + kOffsetSize); + if (size != kEventSize) { + // unknown error, events parsed may be wrong, remove all + events.clear(); + break; + } + + int32_t token = *reinterpret_cast(mBuffer + offset + kOffsetToken); + int32_t type = *reinterpret_cast(mBuffer + offset + kOffsetType); + int64_t timestamp = *reinterpret_cast(mBuffer + offset + kOffsetTimestamp); + + ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32 + ", timestamp %" PRId64, + offset, atomicCounter, token, type, timestamp); + + EventType event = { + .timestamp = timestamp, + .sensorHandle = token, + .sensorType = static_cast(type), + }; + event.u.data = android::hardware::hidl_array( + reinterpret_cast(mBuffer + offset + kOffsetData)); + + events.push_back(event); + + lastCounter = atomicCounter; + offset += kEventSize; + } + + return events; + } + + virtual ~SensorsTestSharedMemory() { + switch (mType) { + case SharedMemType::ASHMEM: { + if (mSize != 0) { + ::munmap(mBuffer, mSize); + mBuffer = nullptr; + + ::native_handle_close(mNativeHandle); + ::native_handle_delete(mNativeHandle); + + mNativeHandle = nullptr; + mSize = 0; + } + break; + } + case SharedMemType::GRALLOC: { + if (mSize != 0) { + mGrallocWrapper->freeBuffer(mNativeHandle); + mNativeHandle = nullptr; + mSize = 0; + } + break; + } + default: { + if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) { + ALOGE("SensorsTestSharedMemory %p not properly destructed: " + "type %d, native handle %p, size %zu, buffer %p", + this, static_cast(mType), mNativeHandle, mSize, mBuffer); + } + break; + } + } + } + + private: + SensorsTestSharedMemory(SharedMemType type, size_t size) + : mType(type), mSize(0), mBuffer(nullptr) { + native_handle_t* handle = nullptr; + char* buffer = nullptr; + switch (type) { + case SharedMemType::ASHMEM: { + int fd; + handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/); + if (handle != nullptr) { + handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size); + if (handle->data[0] > 0) { + // memory is pinned by default + buffer = static_cast( + ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + if (buffer != reinterpret_cast(MAP_FAILED)) { + break; + } + ::native_handle_close(handle); + } + ::native_handle_delete(handle); + handle = nullptr; + } + break; + } + case SharedMemType::GRALLOC: { + mGrallocWrapper = std::make_unique<::android::GrallocWrapper>(); + if (!mGrallocWrapper->isInitialized()) { + break; + } + + std::pair buf = mGrallocWrapper->allocate(size); + handle = buf.first; + buffer = static_cast(buf.second); + break; + } + default: + break; + } + + if (buffer != nullptr) { + mNativeHandle = handle; + mSize = size; + mBuffer = buffer; + } + } SharedMemType mType; native_handle_t* mNativeHandle;