C++程序  |  585行  |  21.66 KB

/*
 * 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 <hardware/sensors.h>  // for sensor type strings
#include <log/log.h>
#include <utils/SystemClock.h>

#include <cinttypes>

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<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
                                                      bool clearBeforeStart,
                                                      bool changeCollection) {
    return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart,
                         changeCollection);
}

std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
                                                      SensorsHidlEnvironmentBase* environment,
                                                      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) {
        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<int>(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<int>(reportMode)
        << "expected=" << static_cast<int>(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<int>(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<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >>
                     static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
    return r >= static_cast<unsigned int>(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<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);
}

void SensorsHidlTestBase::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
}

void SensorsHidlTestBase::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);
}

void SensorsHidlTestBase::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);

    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));
}