Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9cbdea4 authored by Yu Shan's avatar Yu Shan
Browse files

Add VTS for VUR.

Add VTS for testing subscription with variable update rate on.

Test: atest VtsHalAutomotiveVehicle_TargetTest on reference VHAL.
Bug: 323073584
Change-Id: I3c8f4e87ee11487466a1b75ae611cb58f84d8ef5
parent 2385eb04
Loading
Loading
Loading
Loading
+114 −9
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@

#include <chrono>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -63,6 +64,7 @@ using ::android::frameworks::automotive::vhal::IHalPropConfig;
using ::android::frameworks::automotive::vhal::IHalPropValue;
using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
using ::android::frameworks::automotive::vhal::IVhalClient;
using ::android::frameworks::automotive::vhal::SubscribeOptionsBuilder;
using ::android::frameworks::automotive::vhal::VhalClientResult;
using ::android::hardware::getAllHalInstanceNames;
using ::android::hardware::Sanitize;
@@ -83,8 +85,8 @@ struct ServiceDescriptor {
class VtsVehicleCallback final : public ISubscriptionCallback {
  private:
    std::mutex mLock;
    std::unordered_map<int32_t, size_t> mEventsCount GUARDED_BY(mLock);
    std::unordered_map<int32_t, std::vector<int64_t>> mEventTimestamps GUARDED_BY(mLock);
    std::unordered_map<int32_t, std::vector<std::unique_ptr<IHalPropValue>>> mEvents
            GUARDED_BY(mLock);
    std::condition_variable mEventCond;

  public:
@@ -93,8 +95,7 @@ class VtsVehicleCallback final : public ISubscriptionCallback {
            std::lock_guard<std::mutex> lockGuard(mLock);
            for (auto& value : values) {
                int32_t propId = value->getPropId();
                mEventsCount[propId] += 1;
                mEventTimestamps[propId].push_back(value->getTimestamp());
                mEvents[propId].push_back(std::move(value->clone()));
            }
        }
        mEventCond.notify_one();
@@ -110,20 +111,37 @@ class VtsVehicleCallback final : public ISubscriptionCallback {
        std::unique_lock<std::mutex> uniqueLock(mLock);
        return mEventCond.wait_for(uniqueLock, timeout, [this, propId, expectedEvents] {
            ScopedLockAssertion lockAssertion(mLock);
            return mEventsCount[propId] >= expectedEvents;
            return mEvents[propId].size() >= expectedEvents;
        });
    }

    std::vector<std::unique_ptr<IHalPropValue>> getEvents(int32_t propId) {
        std::lock_guard<std::mutex> lockGuard(mLock);
        std::vector<std::unique_ptr<IHalPropValue>> events;
        if (mEvents.find(propId) == mEvents.end()) {
            return events;
        }
        for (const auto& eventPtr : mEvents[propId]) {
            events.push_back(std::move(eventPtr->clone()));
        }
        return events;
    }

    std::vector<int64_t> getEventTimestamps(int32_t propId) {
        {
        std::lock_guard<std::mutex> lockGuard(mLock);
            return mEventTimestamps[propId];
        std::vector<int64_t> timestamps;
        if (mEvents.find(propId) == mEvents.end()) {
            return timestamps;
        }
        for (const auto& valuePtr : mEvents[propId]) {
            timestamps.push_back(valuePtr->getTimestamp());
        }
        return timestamps;
    }

    void reset() {
        std::lock_guard<std::mutex> lockGuard(mLock);
        mEventsCount.clear();
        mEvents.clear();
    }
};

@@ -545,6 +563,93 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeAndUnsubscribe) {
            << "Expect not to get events after unsubscription";
}

bool isVariableUpdateRateSupported(const std::unique_ptr<IHalPropConfig>& config, int32_t areaId) {
    for (const auto& areaConfigPtr : config->getAreaConfigs()) {
        if (areaConfigPtr->getAreaId() == areaId &&
            areaConfigPtr->isVariableUpdateRateSupported()) {
            return true;
        }
    }
    return false;
}

// Test subscribe with variable update rate enabled if supported.
TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribe_enableVurIfSupported) {
    ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribe_enableVurIfSupported");

    int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
    if (!checkIsSupported(propId)) {
        GTEST_SKIP() << "Property: " << propId << " is not supported, skip the test";
    }
    if (!mVhalClient->isAidlVhal()) {
        GTEST_SKIP() << "Variable update rate is only supported by AIDL VHAL";
    }

    auto propConfigsResult = mVhalClient->getPropConfigs({propId});

    ASSERT_TRUE(propConfigsResult.ok()) << "Failed to get property config for PERF_VEHICLE_SPEED: "
                                        << "error: " << propConfigsResult.error().message();
    ASSERT_EQ(propConfigsResult.value().size(), 1u)
            << "Expect to return 1 config for PERF_VEHICLE_SPEED";
    auto& propConfig = propConfigsResult.value()[0];
    float maxSampleRate = propConfig->getMaxSampleRate();
    if (maxSampleRate < 1) {
        GTEST_SKIP() << "Sample rate for vehicle speed < 1 times/sec, skip test since it would "
                        "take too long";
    }
    // PERF_VEHICLE_SPEED is a global property, so areaId is 0.
    if (!isVariableUpdateRateSupported(propConfig, /* areaId= */ 0)) {
        GTEST_SKIP() << "Variable update rate is not supported for PERF_VEHICLE_SPEED, "
                     << "skip testing";
    }

    auto client = mVhalClient->getSubscriptionClient(mCallback);
    ASSERT_NE(client, nullptr) << "Failed to get subscription client";
    SubscribeOptionsBuilder builder(propId);
    // By default variable update rate is true.
    builder.setSampleRate(maxSampleRate);
    auto option = builder.build();

    auto result = client->subscribe({option});

    ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
                                             ", error: %s",
                                             propId, result.error().message().c_str());

    ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, 1, std::chrono::seconds(2)))
            << "Must get at least 1 events within 2 seconds after subscription for rate: "
            << maxSampleRate;

    // Sleep for 1 seconds to wait for more possible events to arrive.
    std::this_thread::sleep_for(std::chrono::seconds(1));

    client->unsubscribe({propId});

    auto events = mCallback->getEvents(propId);
    if (events.size() == 1) {
        // We only received one event, the value is not changing so nothing to check here.
        return;
    }

    // Sort the values by the timestamp.
    std::map<int64_t, float> valuesByTimestamp;
    for (size_t i = 0; i < events.size(); i++) {
        valuesByTimestamp[events[i]->getTimestamp()] = events[i]->getFloatValues()[0];
    }

    size_t i = 0;
    float previousValue;
    for (const auto& [_, value] : valuesByTimestamp) {
        if (i == 0) {
            previousValue = value;
        } else {
            ASSERT_FALSE(value != previousValue) << "received duplicate value: " << value
                                                 << " when variable update rate is true";
            previousValue = value;
        }
    }
}

// Test subscribe() with an invalid property.
TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeInvalidProp) {
    ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeInvalidProp");