Add VTS test for timestamp for AIDL backend.

The expected behavior for timestamp was not clearly defined in HIDL.
In AIDL, we add clearer definition based on the existing HIDL ref
impl's behavior. This CL add VTS test to enforce these behavior for
AIDL backend.

Test: atest VtsHalAutomotiveVehicle_TargetTest
Bug: 225191802
Change-Id: Ic208d6ac20cb7b820249c9b545c7b3a83528a1dd
This commit is contained in:
Yu Shan 2022-03-18 14:34:25 -07:00
parent 9c15ed74b6
commit 4569ef5542

View file

@ -30,6 +30,7 @@
#include <hidl/ServiceManagement.h>
#include <inttypes.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <chrono>
#include <mutex>
@ -67,6 +68,7 @@ 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::condition_variable mEventCond;
public:
@ -74,7 +76,9 @@ class VtsVehicleCallback final : public ISubscriptionCallback {
{
std::lock_guard<std::mutex> lockGuard(mLock);
for (auto& value : values) {
mEventsCount[value->getPropId()] += 1;
int32_t propId = value->getPropId();
mEventsCount[propId] += 1;
mEventTimestamps[propId].push_back(value->getTimestamp());
}
}
mEventCond.notify_one();
@ -94,6 +98,13 @@ class VtsVehicleCallback final : public ISubscriptionCallback {
});
}
std::vector<int64_t> getEventTimestamps(int32_t propId) {
{
std::lock_guard<std::mutex> lockGuard(mLock);
return mEventTimestamps[propId];
}
}
void reset() {
std::lock_guard<std::mutex> lockGuard(mLock);
mEventsCount.clear();
@ -285,19 +296,59 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeAndUnsubscribe) {
int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
std::vector<SubscribeOptions> options = {
SubscribeOptions{.propId = propId, .sampleRate = 10.0}};
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 minSampleRate = propConfig->getMinSampleRate();
float maxSampleRate = propConfig->getMaxSampleRate();
if (minSampleRate < 1) {
GTEST_SKIP() << "Sample rate for vehicle speed < 1 times/sec, skip test since it would "
"take too long";
}
auto client = mVhalClient->getSubscriptionClient(mCallback);
ASSERT_NE(client, nullptr) << "Failed to get subscription client";
auto result = client->subscribe(options);
auto result = client->subscribe({{.propId = propId, .sampleRate = minSampleRate}});
ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
", error: %s",
propId, result.error().message().c_str());
ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, 10, std::chrono::seconds(10)))
<< "Didn't get enough events for subscription";
if (mVhalClient->isAidlVhal()) {
// Skip checking timestamp for HIDL because the behavior for sample rate and timestamp is
// only specified clearly for AIDL.
// Timeout is 2 seconds, which gives a 1 second buffer.
ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, std::floor(minSampleRate),
std::chrono::seconds(2)))
<< "Didn't get enough events for subscribing to minSampleRate";
}
result = client->subscribe({{.propId = propId, .sampleRate = maxSampleRate}});
ASSERT_TRUE(result.ok()) << StringPrintf("Failed to subscribe to property: %" PRId32
", error: %s",
propId, result.error().message().c_str());
if (mVhalClient->isAidlVhal()) {
ASSERT_TRUE(mCallback->waitForExpectedEvents(propId, std::floor(maxSampleRate),
std::chrono::seconds(2)))
<< "Didn't get enough events for subscribing to maxSampleRate";
std::unordered_set<int64_t> timestamps;
// Event event should have a different timestamp.
for (const int64_t& eventTimestamp : mCallback->getEventTimestamps(propId)) {
ASSERT_TRUE(timestamps.find(eventTimestamp) == timestamps.end())
<< "two events for the same property must not have the same timestamp";
timestamps.insert(eventTimestamp);
}
}
result = client->unsubscribe({propId});
ASSERT_TRUE(result.ok()) << StringPrintf("Failed to unsubscribe to property: %" PRId32
@ -325,6 +376,49 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeInvalidProp) {
kInvalidProp);
}
// Test the timestamp returned in GetValues results is the timestamp when the value is retrieved.
TEST_P(VtsHalAutomotiveVehicleTargetTest, testGetValuesTimestampAIDL) {
if (!mVhalClient->isAidlVhal()) {
GTEST_SKIP() << "Skip checking timestamp for HIDL because the behavior is only specified "
"for AIDL";
}
int32_t propId = toInt(VehicleProperty::PARKING_BRAKE_ON);
auto prop = mVhalClient->createHalPropValue(propId);
auto result = mVhalClient->getValueSync(*prop);
ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
", error: %s",
propId, result.error().message().c_str());
ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
ASSERT_EQ(result.value()->getInt32Values().size(), 1u) << "Result must contain 1 int value";
bool parkBrakeOnValue1 = (result.value()->getInt32Values()[0] == 1);
int64_t timestampValue1 = result.value()->getTimestamp();
result = mVhalClient->getValueSync(*prop);
ASSERT_TRUE(result.ok()) << StringPrintf("Failed to get value for property: %" PRId32
", error: %s",
propId, result.error().message().c_str());
ASSERT_NE(result.value(), nullptr) << "Result value must not be null";
ASSERT_EQ(result.value()->getInt32Values().size(), 1u) << "Result must contain 1 int value";
bool parkBarkeOnValue2 = (result.value()->getInt32Values()[0] == 1);
int64_t timestampValue2 = result.value()->getTimestamp();
if (parkBarkeOnValue2 == parkBrakeOnValue1) {
ASSERT_EQ(timestampValue2, timestampValue1)
<< "getValue result must contain a timestamp updated when the value was updated, if"
"the value does not change, expect the same timestamp";
} else {
ASSERT_GT(timestampValue2, timestampValue1)
<< "getValue result must contain a timestamp updated when the value was updated, if"
"the value changes, expect the newer value has a larger timestamp";
}
}
std::vector<ServiceDescriptor> getDescriptors() {
std::vector<ServiceDescriptor> descriptors;
for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {