diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp index f8ef8cba61..c45c000c3c 100644 --- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp +++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -45,8 +46,10 @@ using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions; using ::aidl::android::hardware::automotive::vehicle::VehicleArea; using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus; using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType; using ::android::getAidlHalInstanceNames; +using ::android::uptimeMillis; using ::android::base::ScopedLockAssertion; using ::android::base::StringPrintf; using ::android::frameworks::automotive::vhal::HalPropError; @@ -57,8 +60,11 @@ using ::android::frameworks::automotive::vhal::IVhalClient; using ::android::hardware::getAllHalInstanceNames; using ::android::hardware::Sanitize; using ::android::hardware::automotive::vehicle::toInt; +using ::android::hardware::automotive::vehicle::VhalResult; constexpr int32_t kInvalidProp = 0x31600207; +// The timeout for retrying getting prop value after setting prop value. +constexpr int64_t kRetryGetPropAfterSetPropTimeoutMillis = 10'000; struct ServiceDescriptor { std::string name; @@ -115,6 +121,10 @@ class VtsVehicleCallback final : public ISubscriptionCallback { class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam { protected: bool checkIsSupported(int32_t propertyId); + VehiclePropertyStatus getStatus(const IHalPropValue& halPropValue); + bool isUnavailable(const VhalResult>& result); + bool isResultOkayWithValue(const VhalResult>& result, + int32_t value); public: virtual void SetUp() override { @@ -225,6 +235,41 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, getInvalidProp) { "Expect failure to get property for invalid prop: %" PRId32, kInvalidProp); } +VehiclePropertyStatus VtsHalAutomotiveVehicleTargetTest::getStatus( + const IHalPropValue& halPropValue) { + if (mVhalClient->isAidlVhal()) { + return reinterpret_cast< + const aidl::android::hardware::automotive::vehicle::VehiclePropValue*>( + halPropValue.toVehiclePropValue()) + ->status; + } + return static_cast( + reinterpret_cast( + halPropValue.toVehiclePropValue()) + ->status); +} + +bool VtsHalAutomotiveVehicleTargetTest::isResultOkayWithValue( + const VhalResult>& result, int32_t value) { + return result.ok() && result.value() != nullptr && + getStatus(*(result.value())) == VehiclePropertyStatus::AVAILABLE && + result.value()->getInt32Values().size() == 1 && + result.value()->getInt32Values()[0] == value; +} + +bool VtsHalAutomotiveVehicleTargetTest::isUnavailable( + const VhalResult>& result) { + if (!result.ok()) { + return result.error().code() == StatusCode::NOT_AVAILABLE; + } + if (result.value() != nullptr && + getStatus(*(result.value())) == VehiclePropertyStatus::UNAVAILABLE) { + return true; + } + + return false; +} + // Test set() on read_write properties. TEST_P(VtsHalAutomotiveVehicleTargetTest, setProp) { ALOGD("VtsHalAutomotiveVehicleTargetTest::setProp"); @@ -252,6 +297,14 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, setProp) { auto propToGet = mVhalClient->createHalPropValue(propId); auto getValueResult = mVhalClient->getValueSync(*propToGet); + if (isUnavailable(getValueResult)) { + ALOGW("getProperty for %" PRId32 + " returns NOT_AVAILABLE, " + "skip testing setProp", + propId); + return; + } + ASSERT_TRUE(getValueResult.ok()) << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId, getValueResult.error().message().c_str()); @@ -264,17 +317,48 @@ TEST_P(VtsHalAutomotiveVehicleTargetTest, setProp) { "Expect exactly 1 int value for boolean property: %" PRId32 ", got %zu", propId, intValueSize); - int setValue = value.getInt32Values()[0] == 1 ? 0 : 1; + int32_t setValue = value.getInt32Values()[0] == 1 ? 0 : 1; auto propToSet = mVhalClient->createHalPropValue(propId); propToSet->setInt32Values({setValue}); auto setValueResult = mVhalClient->setValueSync(*propToSet); + if (!setValueResult.ok() && + setValueResult.error().code() == StatusCode::NOT_AVAILABLE) { + ALOGW("setProperty for %" PRId32 + " returns NOT_AVAILABLE, " + "skip verifying getProperty returns the same value", + propId); + return; + } + ASSERT_TRUE(setValueResult.ok()) << StringPrintf("Failed to set value for property: %" PRId32 ", error: %s", propId, setValueResult.error().message().c_str()); + // Retry getting the value until we pass the timeout. getValue might not return + // the expected value immediately since setValue is async. + auto timeoutMillis = uptimeMillis() + kRetryGetPropAfterSetPropTimeoutMillis; + + while (true) { + getValueResult = mVhalClient->getValueSync(*propToGet); + if (isResultOkayWithValue(getValueResult, setValue)) { + break; + } + if (uptimeMillis() >= timeoutMillis) { + // Reach timeout, the following assert should fail. + break; + } + // Sleep for 100ms between each getValueSync retry. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + if (isUnavailable(getValueResult)) { + ALOGW("getProperty for %" PRId32 + " returns NOT_AVAILABLE, " + "skip verifying the return value", + propId); + return; + } - // check set success - getValueResult = mVhalClient->getValueSync(*propToGet); ASSERT_TRUE(getValueResult.ok()) << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId, getValueResult.error().message().c_str());