mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 06:22:53 +00:00
Merge changes from topics "aidl_vhal_vts", "vhalresult" into tm-dev
* changes: Define VhalResult alias. Migrate VHAL VTS to be AIDL compatible.
This commit is contained in:
@@ -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",
|
||||
],
|
||||
}
|
||||
@@ -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);
|
||||
@@ -24,5 +24,10 @@
|
||||
{
|
||||
"name": "DefaultVehicleHalTest"
|
||||
}
|
||||
],
|
||||
"auto-presubmit": [
|
||||
{
|
||||
"name": "VtsHalAutomotiveVehicle_TargetTest"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace fake {
|
||||
|
||||
class FakeVehicleHardware : public IVehicleHardware {
|
||||
public:
|
||||
using ValueResultType = android::base::Result<VehiclePropValuePool::RecyclableType, VhalError>;
|
||||
using ValueResultType = VhalResult<VehiclePropValuePool::RecyclableType>;
|
||||
|
||||
FakeVehicleHardware();
|
||||
|
||||
@@ -90,7 +90,7 @@ class FakeVehicleHardware : public IVehicleHardware {
|
||||
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 @@ class FakeVehicleHardware : public IVehicleHardware {
|
||||
// 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;
|
||||
|
||||
@@ -68,8 +68,6 @@ using ::android::base::Result;
|
||||
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 @@ VehiclePropValuePool::RecyclableType FakeVehicleHardware::createApPowerStateReq(
|
||||
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 @@ bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId) {
|
||||
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 @@ FakeVehicleHardware::ValueResultType FakeVehicleHardware::maybeGetSpecialValue(
|
||||
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 @@ StatusCode FakeVehicleHardware::setValues(std::shared_ptr<const SetValuesCallbac
|
||||
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);
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ class FakeObd2Frame final {
|
||||
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);
|
||||
|
||||
@@ -46,8 +46,6 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
|
||||
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 @@ void FakeObd2Frame::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ Result<VehiclePropValuePool::RecyclableType, VhalError> FakeObd2Frame::getObd2Fr
|
||||
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 @@ Result<VehiclePropValuePool::RecyclableType, VhalError> FakeObd2Frame::getObd2Dt
|
||||
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 {};
|
||||
|
||||
@@ -39,7 +39,7 @@ constexpr char kUserHalDumpOption[] = "--user-hal";
|
||||
// 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) {}
|
||||
|
||||
|
||||
@@ -44,8 +44,6 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
|
||||
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 REMOVE_USER = toInt(VehicleProperty::REMOVE_USER);
|
||||
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 @@ Result<int32_t, VhalError> getRequestId(const VehiclePropValue& value) {
|
||||
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();
|
||||
|
||||
@@ -50,9 +50,9 @@ class PendingRequestPool final {
|
||||
// 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;
|
||||
|
||||
@@ -43,9 +43,8 @@ namespace vehicle {
|
||||
// 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 @@ class VehiclePropertyStore final {
|
||||
// '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.
|
||||
|
||||
@@ -251,9 +251,16 @@ class VhalError final {
|
||||
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 @@ aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(
|
||||
}
|
||||
|
||||
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 @@ ndk::ScopedAStatus toScopedAStatus(
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ using ::android::base::Result;
|
||||
// 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 @@ PendingRequestPool::~PendingRequestPool() {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -39,8 +39,6 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
|
||||
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 @@ VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
|
||||
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 @@ void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
|
||||
};
|
||||
}
|
||||
|
||||
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 @@ std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
|
||||
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);
|
||||
|
||||
@@ -37,7 +37,6 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
|
||||
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, testGetAllConfigs) {
|
||||
}
|
||||
|
||||
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, testGetConfig) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -763,7 +763,7 @@ TEST(VehicleUtilsTest, testConcurrentQueueDeactivateNotifyWaitingThread) {
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -58,8 +58,7 @@ class ConnectedClient {
|
||||
// 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.
|
||||
|
||||
@@ -45,7 +45,6 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi
|
||||
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 @@ class DefaultVehicleHal final : public aidl::android::hardware::automotive::vehi
|
||||
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*>
|
||||
|
||||
@@ -196,8 +196,7 @@ const void* ConnectedClient::id() {
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@@ -600,7 +600,7 @@ ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& prop
|
||||
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 @@ IVehicleHardware* DefaultVehicleHal::getHardware() {
|
||||
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 @@ Result<void, VhalError> DefaultVehicleHal::checkWritePermission(
|
||||
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()) {
|
||||
|
||||
40
automotive/vehicle/vts/Android.bp
Normal file
40
automotive/vehicle/vts/Android.bp
Normal file
@@ -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,
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
# Bug component: 533426
|
||||
shanyu@google.com
|
||||
kwangsudo@google.com
|
||||
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user