Merge changes from topics "aidl_vhal_vts", "vhalresult" into tm-dev
* changes:
Define VhalResult alias.
Migrate VHAL VTS to be AIDL compatible.
diff --git a/automotive/vehicle/2.0/vts/functional/Android.bp b/automotive/vehicle/2.0/vts/functional/Android.bp
deleted file mode 100644
index e64e942..0000000
--- a/automotive/vehicle/2.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "hardware_interfaces_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_test {
- name: "VtsHalAutomotiveVehicleV2_0TargetTest",
- defaults: [
- "VtsHalTargetTestDefaults",
- ],
- srcs: [
- "VtsHalAutomotiveVehicleV2_0TargetTest.cpp",
- ],
- shared_libs: [
- "libbase",
- "libhidlbase",
- "liblog",
- ],
- static_libs: [
- "android.hardware.automotive.vehicle@2.0",
- ],
- test_suites: [
- "vts",
- "general-tests",
- ],
-}
diff --git a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp b/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
deleted file mode 100644
index 8adec84..0000000
--- a/automotive/vehicle/2.0/vts/functional/VtsHalAutomotiveVehicleV2_0TargetTest.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-#define LOG_TAG "VtsHalAutomotiveVehicle"
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <utils/Log.h>
-#include <unordered_set>
-
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-
-using namespace android::hardware::automotive::vehicle::V2_0;
-using ::android::sp;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-
-constexpr auto kTimeout = std::chrono::milliseconds(500);
-constexpr auto kInvalidProp = 0x31600207;
-
-class VtsVehicleCallback : public IVehicleCallback {
- private:
- using MutexGuard = std::lock_guard<std::mutex>;
- using HidlVecOfValues = hidl_vec<VehiclePropValue>;
- std::mutex mLock;
- std::condition_variable mEventCond;
- std::vector<HidlVecOfValues> mReceivedEvents;
-
- public:
- Return<void> onPropertyEvent(const hidl_vec<VehiclePropValue>& values) override {
- {
- MutexGuard guard(mLock);
- mReceivedEvents.push_back(values);
- }
- mEventCond.notify_one();
- return Return<void>();
- }
-
- Return<void> onPropertySet(const VehiclePropValue& /* value */) override {
- return Return<void>();
- }
- Return<void> onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */,
- int32_t /* areaId */) override {
- return Return<void>();
- }
-
- bool waitForExpectedEvents(size_t expectedEvents) {
- std::unique_lock<std::mutex> g(mLock);
-
- if (expectedEvents == 0 && mReceivedEvents.size() == 0) {
- return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout;
- }
-
- while (expectedEvents != mReceivedEvents.size()) {
- if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) {
- return false;
- }
- }
- return true;
- }
-
- void reset() { mReceivedEvents.clear(); }
-};
-
-class VehicleHalHidlTest : public testing::TestWithParam<std::string> {
- public:
- virtual void SetUp() override {
- mVehicle = IVehicle::getService(GetParam());
- ASSERT_NE(mVehicle.get(), nullptr);
- }
- virtual void TearDown() override {}
-
- sp<IVehicle> mVehicle;
-
- bool isBooleanGlobalProp(int32_t property) {
- return (property & (int)VehiclePropertyType::MASK) == (int)VehiclePropertyType::BOOLEAN &&
- (property & (int)VehicleArea::MASK) == (int)VehicleArea::GLOBAL;
- }
-
- void invokeGet(int32_t property, int32_t areaId) {
- VehiclePropValue requestedValue{};
- requestedValue.prop = property;
- requestedValue.areaId = areaId;
-
- invokeGet(requestedValue);
- }
-
- void invokeGet(const VehiclePropValue& requestedPropValue) {
- mActualValue = VehiclePropValue{}; // reset previous values
-
- StatusCode refStatus;
- VehiclePropValue refValue;
- bool isCalled = false;
- mVehicle->get(requestedPropValue,
- [&refStatus, &refValue, &isCalled](StatusCode status,
- const VehiclePropValue& value) {
- refStatus = status;
- refValue = value;
- isCalled = true;
- });
- ASSERT_TRUE(isCalled) << "callback wasn't called for property: " << requestedPropValue.prop;
-
- mActualValue = refValue;
- mActualStatusCode = refStatus;
- }
-
- VehiclePropValue mActualValue;
- StatusCode mActualStatusCode;
-};
-
-// Test getAllPropConfig() returns at least 4 property configs.
-TEST_P(VehicleHalHidlTest, getAllPropConfigs) {
- ALOGD("VehicleHalHidlTest::getAllPropConfigs");
- bool isCalled = false;
- hidl_vec<VehiclePropConfig> propConfigs;
- mVehicle->getAllPropConfigs([&isCalled, &propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) {
- propConfigs = cfgs;
- isCalled = true;
- });
- ASSERT_TRUE(isCalled);
- ASSERT_GE(propConfigs.size(), 4);
-}
-
-// Test getPropConfig() can query all properties listed in CDD.
-TEST_P(VehicleHalHidlTest, getPropConfigs) {
- ALOGD("VehicleHalHidlTest::getPropConfigs");
- // Check the properties listed in CDD
- hidl_vec<int32_t> properties = {
- (int)VehicleProperty::GEAR_SELECTION, (int)VehicleProperty::NIGHT_MODE,
- (int)VehicleProperty::PARKING_BRAKE_ON, (int)VehicleProperty::PERF_VEHICLE_SPEED};
- bool isCalled = false;
- mVehicle->getPropConfigs(
- properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
- ASSERT_EQ(StatusCode::OK, status);
- ASSERT_EQ(4u, cfgs.size());
- isCalled = true;
- });
- ASSERT_TRUE(isCalled);
-}
-
-// Test getPropConfig() with an invalid propertyId returns an error code.
-TEST_P(VehicleHalHidlTest, getPropConfigsWithInvalidProp) {
- ALOGD("VehicleHalHidlTest::getPropConfigsWithInvalidProp");
- hidl_vec<int32_t> properties = {kInvalidProp};
- bool isCalled = false;
- mVehicle->getPropConfigs(
- properties, [&isCalled](StatusCode status, const hidl_vec<VehiclePropConfig>& cfgs) {
- ASSERT_NE(StatusCode::OK, status);
- ASSERT_EQ(0, cfgs.size());
- isCalled = true;
- });
- ASSERT_TRUE(isCalled);
-}
-
-// Test get() return current value for properties.
-TEST_P(VehicleHalHidlTest, get) {
- ALOGD("VehicleHalHidlTest::get");
- invokeGet((int)VehicleProperty::PERF_VEHICLE_SPEED, 0);
- ASSERT_EQ(StatusCode::OK, mActualStatusCode);
-}
-
-// Test get() with an invalid propertyId return an error codes.
-TEST_P(VehicleHalHidlTest, getInvalidProp) {
- ALOGD("VehicleHalHidlTest::getInvalidProp");
-
- invokeGet(kInvalidProp, 0);
- ASSERT_NE(StatusCode::OK, mActualStatusCode);
-}
-
-// Test set() on read_write properties.
-TEST_P(VehicleHalHidlTest, setProp) {
- ALOGD("VehicleHalHidlTest::setProp");
- hidl_vec<VehiclePropConfig> propConfigs;
- // skip hvac related properties
- std::unordered_set<int32_t> hvacProps = {(int)VehicleProperty::HVAC_DEFROSTER,
- (int)VehicleProperty::HVAC_AC_ON,
- (int)VehicleProperty::HVAC_MAX_AC_ON,
- (int)VehicleProperty::HVAC_MAX_DEFROST_ON,
- (int)VehicleProperty::HVAC_RECIRC_ON,
- (int)VehicleProperty::HVAC_DUAL_ON,
- (int)VehicleProperty::HVAC_AUTO_ON,
- (int)VehicleProperty::HVAC_POWER_ON,
- (int)VehicleProperty::HVAC_AUTO_RECIRC_ON,
- (int)VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON};
- mVehicle->getAllPropConfigs(
- [&propConfigs](const hidl_vec<VehiclePropConfig>& cfgs) { propConfigs = cfgs; });
- for (const VehiclePropConfig& cfg : propConfigs) {
- // test on boolean and writable property
- if (cfg.access == VehiclePropertyAccess::READ_WRITE && isBooleanGlobalProp(cfg.prop) &&
- !hvacProps.count(cfg.prop)) {
- invokeGet(cfg.prop, 0);
- int setValue = mActualValue.value.int32Values[0] == 1 ? 0 : 1;
- VehiclePropValue propToSet = mActualValue;
- propToSet.value.int32Values[0] = setValue;
- ASSERT_EQ(StatusCode::OK, mVehicle->set(propToSet))
- << "Invalid status code for setting property: " << cfg.prop;
- // check set success
- invokeGet(cfg.prop, 0);
- ASSERT_EQ(StatusCode::OK, mActualStatusCode);
- ASSERT_EQ(setValue, mActualValue.value.int32Values[0])
- << "Failed to set value for property: " << cfg.prop;
- }
- }
-}
-
-// Test set() on an read_only property.
-TEST_P(VehicleHalHidlTest, setNotWritableProp) {
- ALOGD("VehicleHalHidlTest::setNotWritableProp");
- invokeGet(static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED), 0);
- ASSERT_EQ(StatusCode::OK, mActualStatusCode);
- VehiclePropValue vehicleSpeed = mActualValue;
-
- ASSERT_EQ(StatusCode::ACCESS_DENIED, mVehicle->set(vehicleSpeed));
-}
-
-// Test subscribe() and unsubscribe().
-TEST_P(VehicleHalHidlTest, subscribeAndUnsubscribe) {
- ALOGD("VehicleHalHidlTest::subscribeAndUnsubscribe");
- const auto prop = static_cast<int>(VehicleProperty::PERF_VEHICLE_SPEED);
- sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
-
- hidl_vec<SubscribeOptions> options = {
- SubscribeOptions{.propId = prop, 100.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
-
- ASSERT_EQ(StatusCode::OK, mVehicle->subscribe(cb, options));
- ASSERT_TRUE(cb->waitForExpectedEvents(10));
-
- ASSERT_EQ(StatusCode::OK, mVehicle->unsubscribe(cb, prop));
- cb->reset();
- ASSERT_FALSE(cb->waitForExpectedEvents(10));
-}
-
-// Test subscribe() with an invalid property.
-TEST_P(VehicleHalHidlTest, subscribeInvalidProp) {
- ALOGD("VehicleHalHidlTest::subscribeInvalidProp");
-
- sp<VtsVehicleCallback> cb = new VtsVehicleCallback();
-
- hidl_vec<SubscribeOptions> options = {SubscribeOptions{
- .propId = kInvalidProp, 10.0, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
-
- ASSERT_NE(StatusCode::OK, mVehicle->subscribe(cb, options));
-}
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VehicleHalHidlTest);
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, VehicleHalHidlTest,
- testing::ValuesIn(android::hardware::getAllHalInstanceNames(IVehicle::descriptor)),
- android::hardware::PrintInstanceNameToString);
diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING
index ff6f3be..7e42554 100644
--- a/automotive/vehicle/TEST_MAPPING
+++ b/automotive/vehicle/TEST_MAPPING
@@ -24,5 +24,10 @@
{
"name": "DefaultVehicleHalTest"
}
+ ],
+ "auto-presubmit": [
+ {
+ "name": "VtsHalAutomotiveVehicle_TargetTest"
+ }
]
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index fa494c6..1c076d3 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -41,7 +41,7 @@
class FakeVehicleHardware : public IVehicleHardware {
public:
- using ValueResultType = android::base::Result<VehiclePropValuePool::RecyclableType, VhalError>;
+ using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
FakeVehicleHardware();
@@ -90,7 +90,7 @@
ValueResultType getValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
- android::base::Result<void, VhalError> setValue(
+ VhalResult<void> setValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
private:
@@ -117,17 +117,17 @@
// Override the properties using config files in 'overrideDir'.
void overrideProperties(const char* overrideDir);
- android::base::Result<void, VhalError> maybeSetSpecialValue(
+ VhalResult<void> maybeSetSpecialValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
bool* isSpecialValue);
ValueResultType maybeGetSpecialValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
bool* isSpecialValue) const;
- android::base::Result<void, VhalError> setApPowerStateReport(
+ VhalResult<void> setApPowerStateReport(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
VehiclePropValuePool::RecyclableType createApPowerStateReq(
aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq state);
- android::base::Result<void, VhalError> setUserHalProp(
+ VhalResult<void> setUserHalProp(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
ValueResultType getUserHalProp(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 233efc8..462506d 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -68,8 +68,6 @@
using ::android::base::StartsWith;
using ::android::base::StringPrintf;
-using StatusError = android::base::Error<VhalError>;
-
const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";
@@ -193,7 +191,7 @@
return req;
}
-Result<void, VhalError> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
+VhalResult<void> FakeVehicleHardware::setApPowerStateReport(const VehiclePropValue& value) {
auto updatedValue = mValuePool->obtain(value);
updatedValue->timestamp = elapsedRealtimeNano();
@@ -270,7 +268,7 @@
return false;
}
-Result<void, VhalError> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
+VhalResult<void> FakeVehicleHardware::setUserHalProp(const VehiclePropValue& value) {
auto result = mFakeUserHal->onSetProperty(value);
if (!result.ok()) {
return StatusError(getErrorCode(result))
@@ -345,8 +343,8 @@
return nullptr;
}
-Result<void, VhalError> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
- bool* isSpecialValue) {
+VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValue& value,
+ bool* isSpecialValue) {
*isSpecialValue = false;
VehiclePropValuePool::RecyclableType updatedValue;
int32_t propId = value.prop;
@@ -442,7 +440,7 @@
return StatusCode::OK;
}
-Result<void, VhalError> FakeVehicleHardware::setValue(const VehiclePropValue& value) {
+VhalResult<void> FakeVehicleHardware::setValue(const VehiclePropValue& value) {
bool isSpecialValue = false;
auto setSpecialValueResult = maybeSetSpecialValue(value, &isSpecialValue);
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h
index ba40f60..4d2ffd0 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/include/FakeObd2Frame.h
@@ -38,11 +38,11 @@
const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig);
void initObd2FreezeFrame(
const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig);
- android::base::Result<VehiclePropValuePool::RecyclableType, VhalError> getObd2FreezeFrame(
+ VhalResult<VehiclePropValuePool::RecyclableType> getObd2FreezeFrame(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue&
requestedPropValue) const;
- android::base::Result<VehiclePropValuePool::RecyclableType, VhalError> getObd2DtcInfo() const;
- android::base::Result<void, VhalError> clearObd2FreezeFrames(
+ VhalResult<VehiclePropValuePool::RecyclableType> getObd2DtcInfo() const;
+ VhalResult<void> clearObd2FreezeFrames(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
static bool isDiagnosticProperty(
const aidl::android::hardware::automotive::vehicle::VehiclePropConfig& propConfig);
diff --git a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
index 0a4affc..5f9f217 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/obd2frame/src/FakeObd2Frame.cpp
@@ -46,8 +46,6 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::android::base::Result;
-using StatusError = android::base::Error<VhalError>;
-
std::unique_ptr<Obd2SensorStore> FakeObd2Frame::fillDefaultObd2Frame(size_t numVendorIntegerSensors,
size_t numVendorFloatSensors) {
std::unique_ptr<Obd2SensorStore> sensorStore(new Obd2SensorStore(
@@ -127,7 +125,7 @@
}
}
-Result<VehiclePropValuePool::RecyclableType, VhalError> FakeObd2Frame::getObd2FreezeFrame(
+VhalResult<VehiclePropValuePool::RecyclableType> FakeObd2Frame::getObd2FreezeFrame(
const VehiclePropValue& requestedPropValue) const {
if (requestedPropValue.value.int64Values.size() != 1) {
return StatusError(StatusCode::INVALID_ARG)
@@ -153,7 +151,7 @@
return readValueResult;
}
-Result<VehiclePropValuePool::RecyclableType, VhalError> FakeObd2Frame::getObd2DtcInfo() const {
+VhalResult<VehiclePropValuePool::RecyclableType> FakeObd2Frame::getObd2DtcInfo() const {
std::vector<int64_t> timestamps;
auto result = mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME);
if (!result.ok()) {
@@ -170,7 +168,7 @@
return outValue;
}
-Result<void, VhalError> FakeObd2Frame::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
+VhalResult<void> FakeObd2Frame::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
if (propValue.value.int64Values.size() == 0) {
mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
return {};
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
index 9c4887c..4ae9c8c 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/include/FakeUserHal.h
@@ -39,7 +39,7 @@
// Class used to emulate a real User HAL behavior through lshal debug requests.
class FakeUserHal final {
public:
- using ValueResultType = android::base::Result<VehiclePropValuePool::RecyclableType, VhalError>;
+ using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
explicit FakeUserHal(std::shared_ptr<VehiclePropValuePool> valuePool) : mValuePool(valuePool) {}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
index e37f619..7748fb6 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/userhal/src/FakeUserHal.cpp
@@ -44,8 +44,6 @@
using ::android::base::Error;
using ::android::base::Result;
-using StatusError = android::base::Error<VhalError>;
-
constexpr int32_t INITIAL_USER_INFO = toInt(VehicleProperty::INITIAL_USER_INFO);
constexpr int32_t SWITCH_USER = toInt(VehicleProperty::SWITCH_USER);
constexpr int32_t CREATE_USER = toInt(VehicleProperty::CREATE_USER);
@@ -53,7 +51,7 @@
constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
-Result<int32_t, VhalError> getRequestId(const VehiclePropValue& value) {
+VhalResult<int32_t> getRequestId(const VehiclePropValue& value) {
if (value.value.int32Values.size() < 1) {
return StatusError(StatusCode::INVALID_ARG)
<< "no int32Values on property: " << value.toString();
@@ -61,7 +59,7 @@
return value.value.int32Values[0];
}
-Result<SwitchUserMessageType, VhalError> getSwitchUserMessageType(const VehiclePropValue& value) {
+VhalResult<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
if (value.value.int32Values.size() < 2) {
return StatusError(StatusCode::INVALID_ARG)
<< "missing switch user message type on property: " << value.toString();
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h b/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
index 4ab8acd..3f8db93 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PendingRequestPool.h
@@ -50,9 +50,9 @@
// added. Otherwise, they would be added to the request pool.
// The callback would be called if requests are not finished within {@code mTimeoutInNano}
// seconds.
- android::base::Result<void, VhalError> addRequests(
- const void* clientId, const std::unordered_set<int64_t>& requestIds,
- std::shared_ptr<const TimeoutCallbackFunc> callback);
+ VhalResult<void> addRequests(const void* clientId,
+ const std::unordered_set<int64_t>& requestIds,
+ std::shared_ptr<const TimeoutCallbackFunc> callback);
// Checks whether the request is currently pending.
bool isRequestPending(const void* clientId, int64_t requestId) const;
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
index cebf95c..ddc4f68 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
@@ -43,9 +43,8 @@
// This class is thread-safe, however it uses blocking synchronization across all methods.
class VehiclePropertyStore final {
public:
- using ValueResultType = android::base::Result<VehiclePropValuePool::RecyclableType, VhalError>;
- using ValuesResultType =
- android::base::Result<std::vector<VehiclePropValuePool::RecyclableType>, VhalError>;
+ using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
+ using ValuesResultType = VhalResult<std::vector<VehiclePropValuePool::RecyclableType>>;
explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
: mValuePool(valuePool) {}
@@ -73,8 +72,8 @@
// 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to
// override an existing value, the status for the existing value would be used for the
// overridden value.
- android::base::Result<void, VhalError> writeValue(
- VehiclePropValuePool::RecyclableType propValue, bool updateStatus = false);
+ VhalResult<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
+ bool updateStatus = false);
// Remove a given property value from the property store. The 'propValue' would be used to
// generate the key for the value to remove.
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index 8ef0218..6d7d131 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -251,9 +251,16 @@
aidl::android::hardware::automotive::vehicle::StatusCode mCode;
};
+// VhalResult is a {@code Result} that contains {@code StatusCode} as error type.
template <class T>
-aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(
- const android::base::Result<T, VhalError>& result) {
+using VhalResult = android::base::Result<T, VhalError>;
+
+// StatusError could be cast to {@code ResultError} with a {@code StatusCode} and should be used
+// as error type for {@VhalResult}.
+using StatusError = android::base::Error<VhalError>;
+
+template <class T>
+aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(const VhalResult<T>& result) {
if (result.ok()) {
return aidl::android::hardware::automotive::vehicle::StatusCode::OK;
}
@@ -261,7 +268,7 @@
}
template <class T>
-int getIntErrorCode(const android::base::Result<T, VhalError>& result) {
+int getIntErrorCode(const VhalResult<T>& result) {
return toInt(getErrorCode(result));
}
@@ -293,12 +300,12 @@
}
template <class T>
-ndk::ScopedAStatus toScopedAStatus(const android::base::Result<T, VhalError>& result) {
+ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result) {
return toScopedAStatus(result, getErrorCode(result));
}
template <class T>
-ndk::ScopedAStatus toScopedAStatus(const android::base::Result<T, VhalError>& result,
+ndk::ScopedAStatus toScopedAStatus(const VhalResult<T>& result,
const std::string& additionalErrorMsg) {
return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
index f8a042d..0196edd 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/PendingRequestPool.cpp
@@ -37,8 +37,6 @@
// At least check every 1s.
constexpr int64_t CHECK_TIME_IN_NANO = 1'000'000'000;
-using StatusError = android::base::Error<VhalError>;
-
} // namespace
PendingRequestPool::PendingRequestPool(int64_t timeoutInNano)
@@ -73,7 +71,7 @@
}
}
-Result<void, VhalError> PendingRequestPool::addRequests(
+VhalResult<void> PendingRequestPool::addRequests(
const void* clientId, const std::unordered_set<int64_t>& requestIds,
std::shared_ptr<const TimeoutCallbackFunc> callback) {
std::scoped_lock<std::mutex> lockGuard(mLock);
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index 776caed..c8fb994 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -39,8 +39,6 @@
using ::android::base::Result;
using ::android::base::StringPrintf;
-using StatusError = android::base::Error<VhalError>;
-
bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
return area == other.area && token == other.token;
}
@@ -88,7 +86,7 @@
return recId;
}
-Result<VehiclePropValuePool::RecyclableType, VhalError> VehiclePropertyStore::readValueLocked(
+VhalResult<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValueLocked(
const RecordId& recId, const Record& record) const REQUIRES(mLock) {
if (auto it = record.values.find(recId); it != record.values.end()) {
return mValuePool->obtain(*(it->second));
@@ -107,8 +105,8 @@
};
}
-Result<void, VhalError> VehiclePropertyStore::writeValue(
- VehiclePropValuePool::RecyclableType propValue, bool updateStatus) {
+VhalResult<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
+ bool updateStatus) {
std::scoped_lock<std::mutex> g(mLock);
int32_t propId = propValue->prop;
@@ -248,7 +246,7 @@
return configs;
}
-Result<const VehiclePropConfig*, VhalError> VehiclePropertyStore::getConfig(int32_t propId) const {
+VhalResult<const VehiclePropConfig*> VehiclePropertyStore::getConfig(int32_t propId) const {
std::scoped_lock<std::mutex> g(mLock);
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
index c8bf1d8..4d6f811 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
@@ -37,7 +37,6 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
-using ::android::base::Result;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::WhenSortedBy;
@@ -103,7 +102,7 @@
}
TEST_F(VehiclePropertyStoreTest, testGetConfig) {
- Result<const VehiclePropConfig*, VhalError> result =
+ VhalResult<const VehiclePropConfig*> result =
mStore->getConfig(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
ASSERT_RESULT_OK(result);
@@ -111,7 +110,7 @@
}
TEST_F(VehiclePropertyStoreTest, testGetConfigWithInvalidPropId) {
- Result<const VehiclePropConfig*, VhalError> result = mStore->getConfig(INVALID_PROP_ID);
+ VhalResult<const VehiclePropConfig*> result = mStore->getConfig(INVALID_PROP_ID);
EXPECT_FALSE(result.ok()) << "expect error when getting a config for an invalid property ID";
EXPECT_EQ(result.error().code(), StatusCode::INVALID_ARG);
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index cc29964..411539b 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -763,7 +763,7 @@
}
TEST(VehicleUtilsTest, testVhalError) {
- Result<void, VhalError> result = Error<VhalError>(StatusCode::INVALID_ARG) << "error message";
+ VhalResult<void> result = Error<VhalError>(StatusCode::INVALID_ARG) << "error message";
ASSERT_EQ(result.error().message(), "error message: INVALID_ARG");
}
diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
index 6ab0e1e..2e7298f 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h
@@ -58,8 +58,7 @@
// Returns {@code INVALID_ARG} error if any of the requestIds are duplicate with one of the
// pending request IDs or {@code TRY_AGAIN} error if the pending request pool is full and could
// no longer add requests.
- android::base::Result<void, VhalError> addRequests(
- const std::unordered_set<int64_t>& requestIds);
+ VhalResult<void> addRequests(const std::unordered_set<int64_t>& requestIds);
// Marks the requests as finished. Returns a list of request IDs that was pending and has been
// finished. It must be a set of the requested request IDs.
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 2db7675..f646b6b 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -45,7 +45,6 @@
public:
using CallbackType =
std::shared_ptr<aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
- using StatusError = android::base::Error<VhalError>;
explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
@@ -211,14 +210,14 @@
const std::vector<aidl::android::hardware::automotive::vehicle::SetValueRequest>&
requests);
- android::base::Result<void, VhalError> checkSubscribeOptions(
+ VhalResult<void> checkSubscribeOptions(
const std::vector<aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
options);
- android::base::Result<void, VhalError> checkReadPermission(
+ VhalResult<void> checkReadPermission(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
- android::base::Result<void, VhalError> checkWritePermission(
+ VhalResult<void> checkWritePermission(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
android::base::Result<const aidl::android::hardware::automotive::vehicle::VehiclePropConfig*>
diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
index 4cfc2be..81d231c 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp
@@ -196,8 +196,7 @@
return reinterpret_cast<const void*>(this);
}
-Result<void, VhalError> ConnectedClient::addRequests(
- const std::unordered_set<int64_t>& requestIds) {
+VhalResult<void> ConnectedClient::addRequests(const std::unordered_set<int64_t>& requestIds) {
return mRequestPool->addRequests(id(), requestIds, getTimeoutCallback());
}
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 76736d7..82f2c1b 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -600,7 +600,7 @@
return vectorToStableLargeParcelable(std::move(configs), output);
}
-Result<void, VhalError> DefaultVehicleHal::checkSubscribeOptions(
+VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
const std::vector<SubscribeOptions>& options) {
for (const auto& option : options) {
int32_t propId = option.propId;
@@ -731,8 +731,7 @@
return mVehicleHardware.get();
}
-Result<void, VhalError> DefaultVehicleHal::checkWritePermission(
- const VehiclePropValue& value) const {
+VhalResult<void> DefaultVehicleHal::checkWritePermission(const VehiclePropValue& value) const {
int32_t propId = value.prop;
auto result = getConfig(propId);
if (!result.ok()) {
@@ -748,8 +747,7 @@
return {};
}
-Result<void, VhalError> DefaultVehicleHal::checkReadPermission(
- const VehiclePropValue& value) const {
+VhalResult<void> DefaultVehicleHal::checkReadPermission(const VehiclePropValue& value) const {
int32_t propId = value.prop;
auto result = getConfig(propId);
if (!result.ok()) {
diff --git a/automotive/vehicle/vts/Android.bp b/automotive/vehicle/vts/Android.bp
new file mode 100644
index 0000000..c8276d7
--- /dev/null
+++ b/automotive/vehicle/vts/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+cc_test {
+ name: "VtsHalAutomotiveVehicle_TargetTest",
+ srcs: [
+ "src/*.cpp",
+ ],
+ static_libs: [
+ "libgtest",
+ "libvhalclient",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libvndksupport",
+ ],
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ "vhalclient_defaults",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ require_root: true,
+}
diff --git a/automotive/vehicle/2.0/vts/functional/OWNERS b/automotive/vehicle/vts/OWNERS
similarity index 71%
rename from automotive/vehicle/2.0/vts/functional/OWNERS
rename to automotive/vehicle/vts/OWNERS
index 8a0f2af..c93a843 100644
--- a/automotive/vehicle/2.0/vts/functional/OWNERS
+++ b/automotive/vehicle/vts/OWNERS
@@ -1,2 +1,3 @@
# Bug component: 533426
+shanyu@google.com
kwangsudo@google.com
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
new file mode 100644
index 0000000..c33f3e9
--- /dev/null
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#define LOG_TAG "VtsHalAutomotiveVehicle"
+
+#include <IVhalClient.h>
+#include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
+#include <android-base/stringprintf.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <inttypes.h>
+#include <utils/Log.h>
+
+#include <chrono>
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+using ::aidl::android::hardware::automotive::vehicle::IVehicle;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+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::VehiclePropertyType;
+using ::android::getAidlHalInstanceNames;
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringPrintf;
+using ::android::frameworks::automotive::vhal::HalPropError;
+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::hardware::getAllHalInstanceNames;
+using ::android::hardware::Sanitize;
+using ::android::hardware::automotive::vehicle::toInt;
+
+constexpr int32_t kInvalidProp = 0x31600207;
+
+struct ServiceDescriptor {
+ std::string name;
+ bool isAidlService;
+};
+
+class VtsVehicleCallback final : public ISubscriptionCallback {
+ private:
+ std::mutex mLock;
+ std::unordered_map<int32_t, size_t> mEventsCount GUARDED_BY(mLock);
+ std::condition_variable mEventCond;
+
+ public:
+ void onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>>& values) override {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ for (auto& value : values) {
+ mEventsCount[value->getPropId()] += 1;
+ }
+ }
+ mEventCond.notify_one();
+ }
+
+ void onPropertySetError([[maybe_unused]] const std::vector<HalPropError>& errors) override {
+ // Do nothing.
+ }
+
+ template <class Rep, class Period>
+ bool waitForExpectedEvents(int32_t propId, size_t expectedEvents,
+ const std::chrono::duration<Rep, Period>& timeout) {
+ std::unique_lock<std::mutex> uniqueLock(mLock);
+ return mEventCond.wait_for(uniqueLock, timeout, [this, propId, expectedEvents] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mEventsCount[propId] >= expectedEvents;
+ });
+ }
+
+ void reset() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mEventsCount.clear();
+ }
+};
+
+class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam<ServiceDescriptor> {
+ public:
+ virtual void SetUp() override {
+ auto descriptor = GetParam();
+ if (descriptor.isAidlService) {
+ mVhalClient = IVhalClient::tryCreateAidlClient(descriptor.name.c_str());
+ } else {
+ mVhalClient = IVhalClient::tryCreateHidlClient(descriptor.name.c_str());
+ }
+
+ ASSERT_NE(mVhalClient, nullptr) << "Failed to connect to VHAL";
+
+ mCallback = std::make_shared<VtsVehicleCallback>();
+ }
+
+ static bool isBooleanGlobalProp(int32_t property) {
+ return (property & toInt(VehiclePropertyType::MASK)) ==
+ toInt(VehiclePropertyType::BOOLEAN) &&
+ (property & toInt(VehicleArea::MASK)) == toInt(VehicleArea::GLOBAL);
+ }
+
+ protected:
+ std::shared_ptr<IVhalClient> mVhalClient;
+ std::shared_ptr<VtsVehicleCallback> mCallback;
+};
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, useAidlBackend) {
+ if (!mVhalClient->isAidlVhal()) {
+ GTEST_SKIP() << "AIDL backend is not available, HIDL backend is used instead";
+ }
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, useHidlBackend) {
+ if (mVhalClient->isAidlVhal()) {
+ GTEST_SKIP() << "AIDL backend is available, HIDL backend is not used";
+ }
+}
+
+// Test getAllPropConfig() returns at least 4 property configs.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, getAllPropConfigs) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::getAllPropConfigs");
+
+ auto result = mVhalClient->getAllPropConfigs();
+
+ ASSERT_TRUE(result.ok()) << "Failed to get all property configs, error: "
+ << result.error().message();
+ ASSERT_GE(result.value().size(), 4u) << StringPrintf(
+ "Expect to get at least 4 property configs, got %zu", result.value().size());
+}
+
+// Test getPropConfigs() can query all properties listed in CDD.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, getRequiredPropConfigs) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::getRequiredPropConfigs");
+
+ // Check the properties listed in CDD
+ std::vector<int32_t> properties = {
+ toInt(VehicleProperty::GEAR_SELECTION), toInt(VehicleProperty::NIGHT_MODE),
+ toInt(VehicleProperty::PARKING_BRAKE_ON), toInt(VehicleProperty::PERF_VEHICLE_SPEED)};
+
+ auto result = mVhalClient->getPropConfigs(properties);
+
+ ASSERT_TRUE(result.ok()) << "Failed to get required property config, error: "
+ << result.error().message();
+ ASSERT_EQ(result.value().size(), 4u)
+ << StringPrintf("Expect to get exactly 4 configs, got %zu", result.value().size());
+}
+
+// Test getPropConfig() with an invalid propertyId returns an error code.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, getPropConfigsWithInvalidProp) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::getPropConfigsWithInvalidProp");
+
+ auto result = mVhalClient->getPropConfigs({kInvalidProp});
+
+ ASSERT_FALSE(result.ok()) << StringPrintf(
+ "Expect failure to get prop configs for invalid prop: %" PRId32, kInvalidProp);
+ ASSERT_NE(result.error().message(), "") << "Expect error message not to be empty";
+}
+
+// Test get() return current value for properties.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, get) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::get");
+
+ int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+ auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
+
+ 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";
+}
+
+// Test get() with an invalid propertyId return an error codes.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, getInvalidProp) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::getInvalidProp");
+
+ auto result = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(kInvalidProp));
+
+ ASSERT_FALSE(result.ok()) << StringPrintf(
+ "Expect failure to get property for invalid prop: %" PRId32, kInvalidProp);
+}
+
+// Test set() on read_write properties.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, setProp) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::setProp");
+
+ // skip hvac related properties
+ std::unordered_set<int32_t> hvacProps = {toInt(VehicleProperty::HVAC_DEFROSTER),
+ toInt(VehicleProperty::HVAC_AC_ON),
+ toInt(VehicleProperty::HVAC_MAX_AC_ON),
+ toInt(VehicleProperty::HVAC_MAX_DEFROST_ON),
+ toInt(VehicleProperty::HVAC_RECIRC_ON),
+ toInt(VehicleProperty::HVAC_DUAL_ON),
+ toInt(VehicleProperty::HVAC_AUTO_ON),
+ toInt(VehicleProperty::HVAC_POWER_ON),
+ toInt(VehicleProperty::HVAC_AUTO_RECIRC_ON),
+ toInt(VehicleProperty::HVAC_ELECTRIC_DEFROSTER_ON)};
+ auto result = mVhalClient->getAllPropConfigs();
+ ASSERT_TRUE(result.ok());
+
+ for (const auto& cfgPtr : result.value()) {
+ const IHalPropConfig& cfg = *cfgPtr;
+ int32_t propId = cfg.getPropId();
+ // test on boolean and writable property
+ if (cfg.getAccess() == toInt(VehiclePropertyAccess::READ_WRITE) &&
+ isBooleanGlobalProp(propId) && !hvacProps.count(propId)) {
+ auto propToGet = mVhalClient->createHalPropValue(propId);
+ auto getValueResult = mVhalClient->getValueSync(*propToGet);
+
+ ASSERT_TRUE(getValueResult.ok())
+ << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s",
+ propId, getValueResult.error().message().c_str());
+ ASSERT_NE(getValueResult.value(), nullptr)
+ << StringPrintf("Result value must not be null for property: %" PRId32, propId);
+
+ const IHalPropValue& value = *getValueResult.value();
+ size_t intValueSize = value.getInt32Values().size();
+ ASSERT_EQ(intValueSize, 1u) << StringPrintf(
+ "Expect exactly 1 int value for boolean property: %" PRId32 ", got %zu", propId,
+ intValueSize);
+
+ int setValue = value.getInt32Values()[0] == 1 ? 0 : 1;
+ auto propToSet = mVhalClient->createHalPropValue(propId);
+ propToSet->setInt32Values({setValue});
+ auto setValueResult = mVhalClient->setValueSync(*propToSet);
+
+ ASSERT_TRUE(setValueResult.ok())
+ << StringPrintf("Failed to set value for property: %" PRId32 ", error: %s",
+ propId, setValueResult.error().message().c_str());
+
+ // 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());
+ ASSERT_NE(getValueResult.value(), nullptr)
+ << StringPrintf("Result value must not be null for property: %" PRId32, propId);
+ ASSERT_EQ(getValueResult.value()->getInt32Values(), std::vector<int32_t>({setValue}))
+ << StringPrintf("Boolean value not updated after set for property: %" PRId32,
+ propId);
+ }
+ }
+}
+
+// Test set() on an read_only property.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, setNotWritableProp) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::setNotWritableProp");
+
+ int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+ auto getValueResult = mVhalClient->getValueSync(*mVhalClient->createHalPropValue(propId));
+ ASSERT_TRUE(getValueResult.ok())
+ << StringPrintf("Failed to get value for property: %" PRId32 ", error: %s", propId,
+ getValueResult.error().message().c_str());
+
+ auto setValueResult = mVhalClient->setValueSync(*getValueResult.value());
+
+ ASSERT_FALSE(setValueResult.ok()) << "Expect set a read-only value to fail";
+ ASSERT_EQ(setValueResult.error().code(), StatusCode::ACCESS_DENIED);
+}
+
+// Test subscribe() and unsubscribe().
+TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeAndUnsubscribe) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeAndUnsubscribe");
+
+ int32_t propId = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+
+ std::vector<SubscribeOptions> options = {
+ SubscribeOptions{.propId = propId, .sampleRate = 10.0}};
+
+ auto client = mVhalClient->getSubscriptionClient(mCallback);
+ ASSERT_NE(client, nullptr) << "Failed to get subscription client";
+
+ auto result = client->subscribe(options);
+
+ 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";
+
+ result = client->unsubscribe({propId});
+ ASSERT_TRUE(result.ok()) << StringPrintf("Failed to unsubscribe to property: %" PRId32
+ ", error: %s",
+ propId, result.error().message().c_str());
+
+ mCallback->reset();
+ ASSERT_FALSE(mCallback->waitForExpectedEvents(propId, 10, std::chrono::seconds(1)))
+ << "Expect not to get events after unsubscription";
+}
+
+// Test subscribe() with an invalid property.
+TEST_P(VtsHalAutomotiveVehicleTargetTest, subscribeInvalidProp) {
+ ALOGD("VtsHalAutomotiveVehicleTargetTest::subscribeInvalidProp");
+
+ std::vector<SubscribeOptions> options = {
+ SubscribeOptions{.propId = kInvalidProp, .sampleRate = 10.0}};
+
+ auto client = mVhalClient->getSubscriptionClient(mCallback);
+ ASSERT_NE(client, nullptr) << "Failed to get subscription client";
+
+ auto result = client->subscribe(options);
+
+ ASSERT_FALSE(result.ok()) << StringPrintf("Expect subscribing to property: %" PRId32 " to fail",
+ kInvalidProp);
+}
+
+std::vector<ServiceDescriptor> getDescriptors() {
+ std::vector<ServiceDescriptor> descriptors;
+ for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {
+ descriptors.push_back({
+ .name = name,
+ .isAidlService = true,
+ });
+ }
+ for (std::string name : getAllHalInstanceNames(IVehicle::descriptor)) {
+ descriptors.push_back({
+ .name = name,
+ .isAidlService = false,
+ });
+ }
+ return descriptors;
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VtsHalAutomotiveVehicleTargetTest);
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, VtsHalAutomotiveVehicleTargetTest,
+ testing::ValuesIn(getDescriptors()),
+ [](const testing::TestParamInfo<ServiceDescriptor>& info) {
+ std::string name = "";
+ if (info.param.isAidlService) {
+ name += "aidl_";
+ } else {
+ name += "hidl_";
+ }
+ name += info.param.name;
+ return Sanitize(name);
+ });
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ return RUN_ALL_TESTS();
+}