diff options
Diffstat (limited to 'sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp')
| -rw-r--r-- | sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp | 1122 |
1 files changed, 35 insertions, 1087 deletions
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp index c18eedd176..47308e13b9 100644 --- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp +++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp @@ -15,583 +15,66 @@ */ #define LOG_TAG "sensors_hidl_hal_test" -#include <VtsHalHidlTargetTestBase.h> -#include <VtsHalHidlTargetTestEnvBase.h> -#include <android-base/logging.h> + +#include "SensorsHidlEnvironmentV1_0.h" +#include "sensors-vts-utils/SensorsHidlTestBase.h" + #include <android/hardware/sensors/1.0/ISensors.h> #include <android/hardware/sensors/1.0/types.h> -#include <cutils/ashmem.h> -#include <hardware/sensors.h> // for sensor type strings #include <log/log.h> #include <utils/SystemClock.h> -#include "GrallocWrapper.h" -#include <algorithm> #include <cinttypes> -#include <cmath> -#include <memory> -#include <mutex> -#include <thread> -#include <unordered_set> #include <vector> -#include <sys/mman.h> -#include <unistd.h> - -using ::android::GrallocWrapper; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::hardware::hidl_string; using ::android::sp; using namespace ::android::hardware::sensors::V1_0; -// Test environment for sensors -class SensorsHidlTest; -class SensorsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { - public: - // get the test environment singleton - static SensorsHidlEnvironment* Instance() { - static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment; - return instance; - } - - virtual void HidlSetUp() override; - virtual void HidlTearDown() override; - - virtual void registerTestServices() override { registerTestService<ISensors>(); } - - // 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<Event>* output); - - // set sensor event collection status - void setCollection(bool enable); - - private: - friend SensorsHidlTest; - // sensors hidl service - sp<ISensors> sensors; - - SensorsHidlEnvironment() {} - - void addEvent(const Event& ev); - void startPollingThread(); - void resetHal(); - static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop); - - bool collectionEnabled; - std::shared_ptr<bool> stopThread; - std::thread pollThread; - std::vector<Event> events; - std::mutex events_mutex; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment); -}; - -void SensorsHidlEnvironment::HidlSetUp() { - resetHal(); - - ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service"; - - collectionEnabled = 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)); -} +// The main test class for SENSORS HIDL HAL. -void SensorsHidlEnvironment::HidlTearDown() { - if (stopThread) { - *stopThread = true; +class SensorsHidlTest : public SensorsHidlTestBase { + protected: + SensorInfo defaultSensorByType(SensorType type) override; + std::vector<SensorInfo> getSensorsList(); + // implementation wrapper + Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override { + return S()->getSensorsList(_hidl_cb); } - pollThread.detach(); -} - -void SensorsHidlEnvironment::resetHal() { - // wait upto 100ms * 10 = 1s for hidl service. - constexpr auto RETRY_DELAY = std::chrono::milliseconds(100); - - std::string step; - bool succeed = false; - for (size_t retry = 10; retry > 0; --retry) { - // this do ... while is for easy error handling - do { - step = "getService()"; - sensors = ISensors::getService( - SensorsHidlEnvironment::Instance()->getServiceName<ISensors>()); - if (sensors == nullptr) { - break; - } - - step = "poll() check"; - // Poke ISensor service. If it has lingering connection from previous generation of - // system server, it will kill itself. There is no intention to handle the poll result, - // which will be done since the size is 0. - if(!sensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) { - break; - } - - step = "getSensorList"; - std::vector<SensorInfo> sensorList; - if (!sensors->getSensorsList( - [&] (const ::android::hardware::hidl_vec<SensorInfo> &list) { - sensorList.reserve(list.size()); - for (size_t i = 0; i < list.size(); ++i) { - sensorList.push_back(list[i]); - } - }).isOk()) { - break; - } - // stop each sensor individually - step = "stop each sensor"; - bool ok = true; - for (const auto &i : sensorList) { - if (!sensors->activate(i.sensorHandle, false).isOk()) { - ok = false; - break; - } - } - if (!ok) { - break; - } - - // mark it done - step = "done"; - succeed = true; - } while(0); + Return<Result> activate(int32_t sensorHandle, bool enabled) override; - if (succeed) { - return; + Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs, + int64_t maxReportLatencyNs) override { + return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); } - // Delay 100ms before retry, hidl service is expected to come up in short time after crash. - ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1); - std::this_thread::sleep_for(RETRY_DELAY); - } - - sensors = nullptr; -} + Return<Result> flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); } -void SensorsHidlEnvironment::catEvents(std::vector<Event>* output) { - std::lock_guard<std::mutex> lock(events_mutex); - if (output) { - output->insert(output->end(), events.begin(), events.end()); - } - events.clear(); -} - -void SensorsHidlEnvironment::setCollection(bool enable) { - std::lock_guard<std::mutex> lock(events_mutex); - collectionEnabled = enable; -} - -void SensorsHidlEnvironment::addEvent(const Event& ev) { - std::lock_guard<std::mutex> lock(events_mutex); - if (collectionEnabled) { - events.push_back(ev); - } -} - -void SensorsHidlEnvironment::startPollingThread() { - stopThread = std::shared_ptr<bool>(new bool(false)); - pollThread = std::thread(pollingThread, this, stopThread); - events.reserve(128); -} - -void SensorsHidlEnvironment::pollingThread( - SensorsHidlEnvironment* env, std::shared_ptr<bool> stop) { - ALOGD("polling thread start"); - bool needExit = *stop; - - while(!needExit) { - env->sensors->poll(64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) { - if (result != Result::OK - || (events.size() == 0 && dynamicSensorsAdded.size() == 0) - || *stop) { - needExit = true; - return; - } - - for (const auto& e : events) { - env->addEvent(e); - } - }); - } - ALOGD("polling thread end"); -} - -class SensorsTestSharedMemory { - public: - static SensorsTestSharedMemory* create(SharedMemType type, size_t size); - SharedMemInfo getSharedMemInfo() const; - char * getBuffer() const; - std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const; - virtual ~SensorsTestSharedMemory(); - private: - SensorsTestSharedMemory(SharedMemType type, size_t size); - - SharedMemType mType; - native_handle_t* mNativeHandle; - size_t mSize; - char* mBuffer; - std::unique_ptr<GrallocWrapper> mGrallocWrapper; - - DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory); -}; - -SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const { - SharedMemInfo mem = { - .type = mType, - .format = SharedMemFormat::SENSORS_EVENT, - .size = static_cast<uint32_t>(mSize), - .memoryHandle = mNativeHandle - }; - return mem; -} - -char * SensorsTestSharedMemory::getBuffer() const { - return mBuffer; -} - -std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const { - - constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH); - constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD); - constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN); - constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE); - constexpr size_t kOffsetAtomicCounter = - static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER); - constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP); - constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA); - - std::vector<Event> events; - std::vector<float> data(16); - - while (offset + kEventSize <= mSize) { - int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter); - if (atomicCounter <= lastCounter) { - ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, lastCounter); - break; + Return<Result> injectSensorData(const Event& event) override { + return S()->injectSensorData(event); } - int32_t size = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetSize); - if (size != kEventSize) { - // unknown error, events parsed may be wrong, remove all - events.clear(); - break; - } - - int32_t token = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetToken); - int32_t type = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetType); - int64_t timestamp = *reinterpret_cast<int64_t *>(mBuffer + offset + kOffsetTimestamp); - - ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32 ", timestamp %" PRId64, - offset, atomicCounter, token, type, timestamp); - - Event event = { - .timestamp = timestamp, - .sensorHandle = token, - .sensorType = static_cast<SensorType>(type), - }; - event.u.data = android::hardware::hidl_array<float, 16> - (reinterpret_cast<float*>(mBuffer + offset + kOffsetData)); + Return<void> registerDirectChannel(const SharedMemInfo& mem, + ISensors::registerDirectChannel_cb _hidl_cb) override; - 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<char *> - (::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); - if (buffer != reinterpret_cast<char*>(MAP_FAILED)) { - break; - } - ::native_handle_close(handle); - } - ::native_handle_delete(handle); - handle = nullptr; - } - break; + Return<Result> unregisterDirectChannel(int32_t channelHandle) override { + return S()->unregisterDirectChannel(channelHandle); } - case SharedMemType::GRALLOC: { - mGrallocWrapper = std::make_unique<GrallocWrapper>(); - if (mGrallocWrapper->getAllocator() == nullptr || mGrallocWrapper->getMapper() == nullptr) { - break; - } - using android::hardware::graphics::common::V1_0::BufferUsage; - using android::hardware::graphics::common::V1_0::PixelFormat; - mapper2::IMapper::BufferDescriptorInfo buf_desc_info = { - .width = static_cast<uint32_t>(size), - .height = 1, - .layerCount = 1, - .usage = static_cast<uint64_t> (BufferUsage::SENSOR_DIRECT_DATA | - BufferUsage::CPU_READ_OFTEN), - .format = PixelFormat::BLOB - }; - - handle = const_cast<native_handle_t *>(mGrallocWrapper->allocate(buf_desc_info)); - if (handle != nullptr) { - mapper2::IMapper::Rect region{0, 0, - static_cast<int32_t>(buf_desc_info.width), - static_cast<int32_t>(buf_desc_info.height)}; - buffer = static_cast<char *> - (mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1)); - if (buffer != nullptr) { - break; - } - mGrallocWrapper->freeBuffer(handle); - handle = nullptr; - } - break; - } - default: - 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->unlock(mNativeHandle); - 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<int>(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; -} - -class SensorEventsChecker { - public: - virtual bool check(const std::vector<Event> &events, std::string *out) const = 0; - virtual ~SensorEventsChecker() {} -}; - -class NullChecker : public SensorEventsChecker { - public: - virtual bool check(const std::vector<Event> &, 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<Event> &events, std::string *out) const { - for (const auto &e : events) { - if (!checkEvent(e, out)) { - return false; - } - } - return true; - } -}; - -class Vec3NormChecker : public SensorEventPerEventChecker { - public: - Vec3NormChecker(float min, float max) : mRange(min, max) {} - static Vec3NormChecker byNominal(float nominal, float allowedError) { - return Vec3NormChecker(nominal - allowedError, nominal + allowedError); - } - virtual bool checkEvent(const Event &event, std::string *out) const { - Vec3 v = event.u.vec3; - float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - if (norm < mRange.first || norm > mRange.second) { - if (out != nullptr) { - std::ostringstream ss; - ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z << ")" - << " has norm " << norm << ", which is beyond range" - << " [" << mRange.first << ", " << mRange.second << "]"; - *out = ss.str(); - } - return false; + Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, + ISensors::configDirectReport_cb _hidl_cb) override { + return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); } - return true; - } - protected: - std::pair<float, float> mRange; -}; - -// The main test class for SENSORS HIDL HAL. -class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase { - public: - virtual void SetUp() override { - } - virtual void TearDown() override { - // stop all sensors - for (auto s : mSensorHandles) { - S()->activate(s, false); - } - mSensorHandles.clear(); + inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; } - // stop all direct report and channels - for (auto c : mDirectChannelHandles) { - // disable all reports - S()->configDirectReport(-1, c, RateLevel::STOP, [] (auto, auto){}); - S()->unregisterDirectChannel(c); + SensorsHidlEnvironmentBase* getEnvironment() override { + return SensorsHidlEnvironmentV1_0::Instance(); } - mDirectChannelHandles.clear(); - } - - protected: - SensorInfo defaultSensorByType(SensorType type); - std::vector<SensorInfo> getSensorsList(); - std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit, - bool clearBeforeStart = true, bool changeCollection = true); - - // implementation wrapper - Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) { - return S()->getSensorsList(_hidl_cb); - } - - Return<Result> activate( - int32_t sensorHandle, bool enabled); - - Return<Result> batch( - int32_t sensorHandle, - int64_t samplingPeriodNs, - int64_t maxReportLatencyNs) { - return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs); - } - - Return<Result> flush(int32_t sensorHandle) { - return S()->flush(sensorHandle); - } - - Return<Result> injectSensorData(const Event& event) { - return S()->injectSensorData(event); - } - - Return<void> registerDirectChannel( - const SharedMemInfo& mem, ISensors::registerDirectChannel_cb _hidl_cb); - - Return<Result> unregisterDirectChannel(int32_t channelHandle) { - return S()->unregisterDirectChannel(channelHandle); - } - - Return<void> configDirectReport( - int32_t sensorHandle, int32_t channelHandle, RateLevel rate, - ISensors::configDirectReport_cb _hidl_cb) { - return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); - } - - inline sp<ISensors>& S() { - return SensorsHidlEnvironment::Instance()->sensors; - } - - inline static SensorFlagBits extractReportMode(uint64_t flag) { - return (SensorFlagBits) (flag - & ((uint64_t) SensorFlagBits::CONTINUOUS_MODE - | (uint64_t) SensorFlagBits::ON_CHANGE_MODE - | (uint64_t) SensorFlagBits::ONE_SHOT_MODE - | (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 isValidType(SensorType 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); - - // checkers - static const Vec3NormChecker sAccelNormChecker; - static const Vec3NormChecker sGyroNormChecker; - - // all sensors and direct channnels used - std::unordered_set<int32_t> mSensorHandles; - std::unordered_set<int32_t> mDirectChannelHandles; }; -const Vec3NormChecker SensorsHidlTest::sAccelNormChecker( - Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f/*m/s^2*/)); -const Vec3NormChecker SensorsHidlTest::sGyroNormChecker( - Vec3NormChecker::byNominal(0.f, 0.1f/*rad/s*/)); - Return<Result> 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 @@ -618,195 +101,6 @@ Return<void> SensorsHidlTest::registerDirectChannel( return Void(); } -std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t nEventLimit, - bool clearBeforeStart, bool changeCollection) { - std::vector<Event> 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) { - SensorsHidlEnvironment::Instance()->setCollection(true); - } - if (clearBeforeStart) { - SensorsHidlEnvironment::Instance()->catEvents(nullptr); - } - - while (timeLimitUs > 0) { - useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs); - usleep(duration); - timeLimitUs -= duration; - - SensorsHidlEnvironment::Instance()->catEvents(&events); - if (events.size() >= nEventLimit) { - break; - } - ALOGV("time to go = %d, events to go = %d", - (int)timeLimitUs, (int)(nEventLimit - events.size())); - } - - if (changeCollection) { - SensorsHidlEnvironment::Instance()->setCollection(false); - } - return events; -} - -void SensorsHidlTest::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<int>(type) << " in android defined range is not checked, " - << "stringType = " << stringType; -#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE - } -} - -void SensorsHidlTest::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<int>(reportMode) - << "expected=" << static_cast<int>(expected); -} - -void SensorsHidlTest::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<int>(reportMode) << " not checked"; - } -} - -// return -1 means no expectation for this type -SensorFlagBits SensorsHidlTest::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 SensorsHidlTest::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) { - unsigned int r = - static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) - >> static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT); - return r >= static_cast<unsigned int>(rate); -} - -bool SensorsHidlTest::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; - } -} - SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) { SensorInfo ret; @@ -951,69 +245,6 @@ TEST_F(SensorsHidlTest, InjectSensorEventData) { ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL)); } -void SensorsHidlTest::testStreamingOperation(SensorType type, - std::chrono::nanoseconds samplingPeriod, - std::chrono::seconds duration, - const SensorEventsChecker &checker) { - std::vector<Event> events; - std::vector<Event> 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 -} - // Test if sensor hal can do UI speed accelerometer streaming properly TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) { testStreamingOperation(SensorType::ACCELEROMETER, @@ -1086,103 +317,6 @@ TEST_F(SensorsHidlTest, MagnetometerStreamingOperationFast) { NullChecker()); } -void SensorsHidlTest::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) { - std::vector<Event> 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<Event> &minDelayEvents(fastToSlow ? events1 : events2); - std::vector<Event> &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); -} - // Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) { testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER); @@ -1201,74 +335,6 @@ TEST_F(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) { testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/); } -void SensorsHidlTest::testBatchingOperation(SensorType type) { - std::vector<Event> 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); - - SensorsHidlEnvironment::Instance()->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*/); - - SensorsHidlEnvironment::Instance()->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)); -} - // Test if sensor hal can do accelerometer batching properly TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) { testBatchingOperation(SensorType::ACCELEROMETER); @@ -1284,124 +350,6 @@ TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) { testBatchingOperation(SensorType::MAGNETIC_FIELD); } -void SensorsHidlTest::testDirectReportOperation( - SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) { - constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH); - constexpr size_t kNEvent = 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<SensorsTestSharedMemory> - 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<useconds_t>(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<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec)); - ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec)); - - int64_t lastTimestamp = 0; - bool typeErrorReported = false; - bool tokenErrorReported = false; - bool timestampErrorReported = false; - std::vector<Event> 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); -} - // Test sensor event direct report with ashmem for accel sensor at normal rate TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) { testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL, @@ -1511,11 +459,11 @@ TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) { } int main(int argc, char **argv) { - ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance()); - ::testing::InitGoogleTest(&argc, argv); - SensorsHidlEnvironment::Instance()->init(&argc, argv); - int status = RUN_ALL_TESTS(); - ALOGI("Test result = %d", status); - return status; + ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance()); + ::testing::InitGoogleTest(&argc, argv); + SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv); + int status = RUN_ALL_TESTS(); + ALOGI("Test result = %d", status); + return status; } // vim: set ts=2 sw=2 |
