mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge "Convert VehicleHalDefaultConfig to JsonConfigLoader."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ceba715278
@@ -89,7 +89,8 @@ class JsonValueParser final {
|
||||
// The main class to parse a VHAL config file in JSON format.
|
||||
class JsonConfigParser {
|
||||
public:
|
||||
android::base::Result<std::vector<ConfigDeclaration>> parseJsonConfig(std::istream& is);
|
||||
android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>> parseJsonConfig(
|
||||
std::istream& is);
|
||||
|
||||
private:
|
||||
JsonValueParser mValueParser;
|
||||
@@ -155,8 +156,13 @@ class JsonConfigLoader final {
|
||||
public:
|
||||
JsonConfigLoader();
|
||||
|
||||
// Loads a JSON file stream and parses it to a list of ConfigDeclarations.
|
||||
android::base::Result<std::vector<ConfigDeclaration>> loadPropConfig(std::istream& is);
|
||||
// Loads a JSON file stream and parses it to a map from propId to ConfigDeclarations.
|
||||
android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>> loadPropConfig(
|
||||
std::istream& is);
|
||||
|
||||
// Loads a JSON config file and parses it to a map from propId to ConfigDeclarations.
|
||||
android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>> loadPropConfig(
|
||||
const std::string& configPath);
|
||||
|
||||
private:
|
||||
std::unique_ptr<jsonconfigloader_impl::JsonConfigParser> mParser;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
|
||||
|
||||
#include <android-base/strings.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -509,25 +510,32 @@ std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
|
||||
return configDecl;
|
||||
}
|
||||
|
||||
Result<std::vector<ConfigDeclaration>> JsonConfigParser::parseJsonConfig(std::istream& is) {
|
||||
Result<std::unordered_map<int32_t, ConfigDeclaration>> JsonConfigParser::parseJsonConfig(
|
||||
std::istream& is) {
|
||||
Json::CharReaderBuilder builder;
|
||||
Json::Value root;
|
||||
std::vector<ConfigDeclaration> configs;
|
||||
std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
|
||||
std::string errs;
|
||||
if (!Json::parseFromStream(builder, is, &root, &errs)) {
|
||||
return Error() << "Failed to parse property config file as JSON, error: " << errs;
|
||||
}
|
||||
if (!root.isObject()) {
|
||||
return Error() << "root element must be an object";
|
||||
}
|
||||
if (!root.isMember("properties") || !root["properties"].isArray()) {
|
||||
return Error() << "Missing 'properties' field in root or the field is not an array";
|
||||
}
|
||||
Json::Value properties = root["properties"];
|
||||
std::vector<std::string> errors;
|
||||
for (unsigned int i = 0; i < properties.size(); i++) {
|
||||
if (auto maybeConfig = parseEachProperty(properties[i], &errors); maybeConfig.has_value()) {
|
||||
configs.push_back(std::move(maybeConfig.value()));
|
||||
configsByPropId[maybeConfig.value().config.prop] = std::move(maybeConfig.value());
|
||||
}
|
||||
}
|
||||
if (!errors.empty()) {
|
||||
return Error() << android::base::Join(errors, '\n');
|
||||
}
|
||||
return configs;
|
||||
return configsByPropId;
|
||||
}
|
||||
|
||||
} // namespace jsonconfigloader_impl
|
||||
@@ -536,11 +544,21 @@ JsonConfigLoader::JsonConfigLoader() {
|
||||
mParser = std::make_unique<jsonconfigloader_impl::JsonConfigParser>();
|
||||
}
|
||||
|
||||
android::base::Result<std::vector<ConfigDeclaration>> JsonConfigLoader::loadPropConfig(
|
||||
std::istream& is) {
|
||||
android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>>
|
||||
JsonConfigLoader::loadPropConfig(std::istream& is) {
|
||||
return mParser->parseJsonConfig(is);
|
||||
}
|
||||
|
||||
android::base::Result<std::unordered_map<int32_t, ConfigDeclaration>>
|
||||
JsonConfigLoader::loadPropConfig(const std::string& configPath) {
|
||||
std::ifstream ifs(configPath.c_str());
|
||||
if (!ifs) {
|
||||
return android::base::Error() << "couldn't open " << configPath << " for parsing.";
|
||||
}
|
||||
|
||||
return loadPropConfig(ifs);
|
||||
}
|
||||
|
||||
} // namespace vehicle
|
||||
} // namespace automotive
|
||||
} // namespace hardware
|
||||
|
||||
@@ -38,7 +38,7 @@ class JsonConfigLoaderUnitTest : public ::testing::Test {
|
||||
JsonConfigLoader mLoader;
|
||||
};
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestBasic) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testBasic) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -53,11 +53,39 @@ TEST_F(JsonConfigLoaderUnitTest, TestBasic) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
ASSERT_EQ(configs[0].config.prop, 291504388);
|
||||
ASSERT_EQ(configs.begin()->second.config.prop, 291504388);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestPropertyIsEnum) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testRootNotObject) {
|
||||
std::istringstream iss(R"(
|
||||
[]
|
||||
)");
|
||||
|
||||
ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "root is not an object must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, testMissingPropertiesField) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"abcd": 1234
|
||||
}
|
||||
)");
|
||||
|
||||
ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Missing 'properties' field must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, testPropertiesFieldNotArray) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties': {'a': 'b'}
|
||||
}
|
||||
)");
|
||||
|
||||
ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
|
||||
<< "'properties' field is not an array must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, testPropertyIsEnum) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -72,11 +100,10 @@ TEST_F(JsonConfigLoaderUnitTest, TestPropertyIsEnum) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
ASSERT_EQ(configs[0].config.prop, toInt(VehicleProperty::INFO_FUEL_CAPACITY));
|
||||
ASSERT_EQ(configs.begin()->second.config.prop, toInt(VehicleProperty::INFO_FUEL_CAPACITY));
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestPropertyEnum_FailInvalidEnum) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testPropertyEnum_FailInvalidEnum) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -89,7 +116,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestPropertyEnum_FailInvalidEnum) {
|
||||
<< "Invalid VehicleProperty enum must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestPropertyEnum_FailInvalidType) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testPropertyEnum_FailInvalidType) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -102,7 +129,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestPropertyEnum_FailInvalidType) {
|
||||
<< "Invalid VehicleProperty type must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestProperty_FailInvalidJson) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testProperty_FailInvalidJson) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -112,7 +139,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestProperty_FailInvalidJson) {
|
||||
ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Invalid JSON format must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigArray) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigArray) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -128,10 +155,10 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigArray) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
ASSERT_EQ(configs[0].config.configArray, std::vector<int>({1, 2, 3}));
|
||||
ASSERT_EQ(configs.begin()->second.config.configArray, std::vector<int>({1, 2, 3}));
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigArrayConstants) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigArrayConstants) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -147,11 +174,12 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigArrayConstants) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
ASSERT_EQ(configs[0].config.configArray, std::vector<int>({1, 2, FUEL_DOOR_REAR_LEFT}));
|
||||
ASSERT_EQ(configs.begin()->second.config.configArray,
|
||||
std::vector<int>({1, 2, FUEL_DOOR_REAR_LEFT}));
|
||||
}
|
||||
|
||||
// We have special logic to deal with GALLON and US_GALLON since they share the same value.
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigArrayUnitGallon) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigArrayUnitGallon) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -166,7 +194,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigArrayUnitGallon) {
|
||||
ASSERT_TRUE(result.ok()) << result.error().message();
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigArrayUnitUsGallon) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigArrayUnitUsGallon) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -181,7 +209,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigArrayUnitUsGallon) {
|
||||
ASSERT_TRUE(result.ok()) << result.error().message();
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigArray_FailInvalidEnum) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigArray_FailInvalidEnum) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -195,7 +223,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigArray_FailInvalidEnum) {
|
||||
<< "Invalid enum in ConfigArray must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigArray_FailNotArray) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigArray_FailNotArray) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -209,7 +237,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigArray_FailNotArray) {
|
||||
<< "ConfigArray is not an array must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigString) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigString) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -225,10 +253,10 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigString) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
ASSERT_EQ(configs[0].config.configString, "test");
|
||||
ASSERT_EQ(configs.begin()->second.config.configString, "test");
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestConfigString_FailNotString) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testConfigString_FailNotString) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -242,7 +270,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestConfigString_FailNotString) {
|
||||
<< "ConfigString is not a String must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestCheckDefaultAccessChangeMode) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testCheckDefaultAccessChangeMode) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -257,12 +285,12 @@ TEST_F(JsonConfigLoaderUnitTest, TestCheckDefaultAccessChangeMode) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const VehiclePropConfig& propConfig = configs[0].config;
|
||||
const VehiclePropConfig& propConfig = configs.begin()->second.config;
|
||||
ASSERT_EQ(propConfig.access, VehiclePropertyAccess::READ);
|
||||
ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::STATIC);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestAccessOverride) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testAccessOverride) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -278,12 +306,12 @@ TEST_F(JsonConfigLoaderUnitTest, TestAccessOverride) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const VehiclePropConfig& propConfig = configs[0].config;
|
||||
const VehiclePropConfig& propConfig = configs.begin()->second.config;
|
||||
ASSERT_EQ(propConfig.access, VehiclePropertyAccess::WRITE);
|
||||
ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::STATIC);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestChangeModeOverride) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testChangeModeOverride) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -299,12 +327,12 @@ TEST_F(JsonConfigLoaderUnitTest, TestChangeModeOverride) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const VehiclePropConfig& propConfig = configs[0].config;
|
||||
const VehiclePropConfig& propConfig = configs.begin()->second.config;
|
||||
ASSERT_EQ(propConfig.access, VehiclePropertyAccess::READ);
|
||||
ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::ON_CHANGE);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestCustomProp) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testCustomProp) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -321,12 +349,12 @@ TEST_F(JsonConfigLoaderUnitTest, TestCustomProp) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const VehiclePropConfig& propConfig = configs[0].config;
|
||||
const VehiclePropConfig& propConfig = configs.begin()->second.config;
|
||||
ASSERT_EQ(propConfig.access, VehiclePropertyAccess::WRITE);
|
||||
ASSERT_EQ(propConfig.changeMode, VehiclePropertyChangeMode::ON_CHANGE);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestCustomProp_FailMissingAccess) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testCustomProp_FailMissingAccess) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -340,7 +368,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestCustomProp_FailMissingAccess) {
|
||||
<< "Missing access for custom property must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestCustomProp_FailMissingChangeMode) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testCustomProp_FailMissingChangeMode) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -354,7 +382,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestCustomProp_FailMissingChangeMode) {
|
||||
<< "Missing change mode for custom property must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestMinSampleRate) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testMinSampleRate) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -370,10 +398,10 @@ TEST_F(JsonConfigLoaderUnitTest, TestMinSampleRate) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
ASSERT_EQ(configs[0].config.minSampleRate, 1);
|
||||
ASSERT_EQ(configs.begin()->second.config.minSampleRate, 1);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestMinSampleRate_FailInvalidType) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testMinSampleRate_FailInvalidType) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -387,7 +415,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestMinSampleRate_FailInvalidType) {
|
||||
<< "Wrong type for MinSampleRate must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestMaxSampleRate) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testMaxSampleRate) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -403,10 +431,10 @@ TEST_F(JsonConfigLoaderUnitTest, TestMaxSampleRate) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
ASSERT_EQ(configs[0].config.maxSampleRate, 1);
|
||||
ASSERT_EQ(configs.begin()->second.config.maxSampleRate, 1);
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestMaxSampleRate_FailInvalidType) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testMaxSampleRate_FailInvalidType) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -420,7 +448,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestMaxSampleRate_FailInvalidType) {
|
||||
<< "Wrong type for MaxSampleRate must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_Simple) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_Simple) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -438,10 +466,10 @@ TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_Simple) {
|
||||
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
ASSERT_EQ(configs[0].initialValue.int32Values, std::vector<int32_t>({1, 2}));
|
||||
ASSERT_EQ(configs.begin()->second.initialValue.int32Values, std::vector<int32_t>({1, 2}));
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_Mixed) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_Mixed) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -463,7 +491,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_Mixed) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const RawPropValues& initialValue = configs[0].initialValue;
|
||||
const RawPropValues& initialValue = configs.begin()->second.initialValue;
|
||||
ASSERT_EQ(initialValue.int32Values, std::vector<int32_t>({1, FUEL_DOOR_REAR_LEFT}));
|
||||
ASSERT_EQ(initialValue.int64Values,
|
||||
std::vector<int64_t>({2, static_cast<int64_t>(FUEL_DOOR_REAR_LEFT)}));
|
||||
@@ -472,7 +500,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_Mixed) {
|
||||
ASSERT_EQ(initialValue.stringValue, "abcd");
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_FailNotObject) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_FailNotObject) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -486,7 +514,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_FailNotObject) {
|
||||
<< "DefaultValue is not an object must cause error";
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_FailInvalidType) {
|
||||
TEST_F(JsonConfigLoaderUnitTest, testDefaultValue_FailInvalidType) {
|
||||
std::istringstream iss(R"(
|
||||
{
|
||||
"properties": [{
|
||||
@@ -521,7 +549,7 @@ TEST_F(JsonConfigLoaderUnitTest, testAreas_Simple) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const VehiclePropConfig& config = configs[0].config;
|
||||
const VehiclePropConfig& config = configs.begin()->second.config;
|
||||
ASSERT_EQ(config.areaConfigs.size(), 1u);
|
||||
const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
|
||||
ASSERT_EQ(areaConfig.minInt32Value, 1);
|
||||
@@ -554,12 +582,14 @@ TEST_F(JsonConfigLoaderUnitTest, testAreas_DefaultValueForEachArea) {
|
||||
auto configs = result.value();
|
||||
ASSERT_EQ(configs.size(), 1u);
|
||||
|
||||
const VehiclePropConfig& config = configs[0].config;
|
||||
const VehiclePropConfig& config = configs.begin()->second.config;
|
||||
ASSERT_EQ(config.areaConfigs.size(), 2u);
|
||||
ASSERT_EQ(config.areaConfigs[0].areaId, HVAC_LEFT);
|
||||
ASSERT_EQ(config.areaConfigs[1].areaId, HVAC_RIGHT);
|
||||
ASSERT_EQ(configs[0].initialAreaValues[HVAC_LEFT], RawPropValues{.int32Values = {1}});
|
||||
ASSERT_EQ(configs[0].initialAreaValues[HVAC_RIGHT], RawPropValues{.int32Values = {2}});
|
||||
ASSERT_EQ(configs.begin()->second.initialAreaValues[HVAC_LEFT],
|
||||
RawPropValues{.int32Values = {1}});
|
||||
ASSERT_EQ(configs.begin()->second.initialAreaValues[HVAC_RIGHT],
|
||||
RawPropValues{.int32Values = {2}});
|
||||
}
|
||||
|
||||
TEST_F(JsonConfigLoaderUnitTest, testAreas_FailInvalidTypeForOneAreaValue) {
|
||||
|
||||
@@ -21,3 +21,27 @@ filegroup {
|
||||
name: "VehicleHalVendorClusterTestProperties_JSON",
|
||||
srcs: ["VendorClusterTestProperties.json"],
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "Prebuilt_VehicleHalDefaultProperties_JSON",
|
||||
filename_from_src: true,
|
||||
src: "DefaultProperties.json",
|
||||
sub_dir: "automotive/vhalconfig/",
|
||||
vendor: true,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "Prebuilt_VehicleHalTestProperties_JSON",
|
||||
filename_from_src: true,
|
||||
src: "TestProperties.json",
|
||||
sub_dir: "automotive/vhalconfig/",
|
||||
vendor: true,
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "Prebuilt_VehicleHalVendorClusterTestProperties_JSON",
|
||||
filename_from_src: true,
|
||||
src: "VendorClusterTestProperties.json",
|
||||
sub_dir: "automotive/vhalconfig/",
|
||||
vendor: true,
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -45,7 +46,8 @@ std::string getTestFilePath(const char* filename) {
|
||||
return baseDir + "/" + filename;
|
||||
}
|
||||
|
||||
Result<std::vector<ConfigDeclaration>> loadConfig(JsonConfigLoader& loader, const char* path) {
|
||||
Result<std::unordered_map<int32_t, ConfigDeclaration>> loadConfig(JsonConfigLoader& loader,
|
||||
const char* path) {
|
||||
std::string configPath = getTestFilePath(path);
|
||||
std::ifstream ifs(configPath.c_str());
|
||||
if (!ifs) {
|
||||
@@ -89,7 +91,9 @@ TEST(DefaultConfigTest, TestCompatibleWithDefaultConfigHeader) {
|
||||
kVendorClusterTestPropertiesConfigFile})) {
|
||||
auto result = loadConfig(loader, file);
|
||||
ASSERT_TRUE(result.ok()) << result.error().message();
|
||||
configsFromJson.insert(configsFromJson.end(), result.value().begin(), result.value().end());
|
||||
for (auto& [propId, configDeclaration] : result.value()) {
|
||||
configsFromJson.push_back(configDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_EQ(configsFromHeaderFile.size(), configsFromJson.size());
|
||||
|
||||
@@ -24,6 +24,7 @@ cc_library {
|
||||
srcs: ["src/*.cpp"],
|
||||
local_include_dirs: ["include"],
|
||||
export_include_dirs: ["include"],
|
||||
cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
|
||||
defaults: [
|
||||
"VehicleHalDefaults",
|
||||
"FakeVehicleHardwareDefaults",
|
||||
@@ -32,18 +33,23 @@ cc_library {
|
||||
|
||||
cc_defaults {
|
||||
name: "FakeVehicleHardwareDefaults",
|
||||
cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
|
||||
header_libs: [
|
||||
"IVehicleHardware",
|
||||
"VehicleHalDefaultConfig",
|
||||
"VehicleHalTestUtilHeaders",
|
||||
],
|
||||
export_header_lib_headers: ["IVehicleHardware"],
|
||||
static_libs: [
|
||||
"VehicleHalJsonConfigLoaderEnableTestProperties",
|
||||
"VehicleHalUtils",
|
||||
"FakeVehicleHalValueGenerators",
|
||||
"FakeObd2Frame",
|
||||
"FakeUserHal",
|
||||
],
|
||||
required: [
|
||||
"Prebuilt_VehicleHalDefaultProperties_JSON",
|
||||
"Prebuilt_VehicleHalTestProperties_JSON",
|
||||
"Prebuilt_VehicleHalVendorClusterTestProperties_JSON",
|
||||
],
|
||||
shared_libs: [
|
||||
"libjsoncpp",
|
||||
],
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
|
||||
|
||||
#include <ConcurrentQueue.h>
|
||||
#include <DefaultConfig.h>
|
||||
#include <ConfigDeclaration.h>
|
||||
#include <FakeObd2Frame.h>
|
||||
#include <FakeUserHal.h>
|
||||
#include <GeneratorHub.h>
|
||||
#include <IVehicleHardware.h>
|
||||
#include <JsonConfigLoader.h>
|
||||
#include <RecurrentTimer.h>
|
||||
#include <VehicleHalTypes.h>
|
||||
#include <VehiclePropertyStore.h>
|
||||
@@ -32,9 +33,9 @@
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/thread_annotations.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
@@ -49,7 +50,8 @@ class FakeVehicleHardware : public IVehicleHardware {
|
||||
|
||||
FakeVehicleHardware();
|
||||
|
||||
explicit FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool);
|
||||
FakeVehicleHardware(std::string defaultConfigDir, std::string overrideConfigDir,
|
||||
bool forceOverride);
|
||||
|
||||
~FakeVehicleHardware();
|
||||
|
||||
@@ -151,17 +153,23 @@ class FakeVehicleHardware : public IVehicleHardware {
|
||||
aidl::android::hardware::automotive::vehicle::SetValueRequest>
|
||||
mPendingSetValueRequests;
|
||||
|
||||
const std::string mDefaultConfigDir;
|
||||
const std::string mOverrideConfigDir;
|
||||
const bool mForceOverride;
|
||||
|
||||
// Only used during initialization.
|
||||
JsonConfigLoader mLoader;
|
||||
|
||||
void init();
|
||||
// Stores the initial value to property store.
|
||||
void storePropInitialValue(const ConfigDeclaration& config);
|
||||
// The callback that would be called when a vehicle property value change happens.
|
||||
void onValueChangeCallback(
|
||||
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
|
||||
// If property "persist.vendor.vhal_init_value_override" is set to true, override the properties
|
||||
// using config files in 'overrideDir'.
|
||||
void maybeOverrideProperties(const char* overrideDir);
|
||||
// Override the properties using config files in 'overrideDir'.
|
||||
void overrideProperties(const char* overrideDir);
|
||||
// Load the config files in format '*.json' from the directory and parse the config files
|
||||
// into a map from property ID to ConfigDeclarations.
|
||||
void loadPropConfigsFromDir(const std::string& dirPath,
|
||||
std::unordered_map<int32_t, ConfigDeclaration>* configs);
|
||||
// Function to be called when a value change event comes from vehicle bus. In our fake
|
||||
// implementation, this function is only called during "--inject-event" dump command.
|
||||
void eventFromVehicleBus(
|
||||
@@ -185,6 +193,8 @@ class FakeVehicleHardware : public IVehicleHardware {
|
||||
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
|
||||
bool isHvacPropAndHvacNotAvailable(int32_t propId);
|
||||
|
||||
std::unordered_map<int32_t, ConfigDeclaration> loadConfigDeclarations();
|
||||
|
||||
std::string dumpAllProperties();
|
||||
std::string dumpOnePropertyByConfig(
|
||||
int rowNumber,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "FakeVehicleHardware.h"
|
||||
|
||||
#include <DefaultConfig.h>
|
||||
#include <FakeObd2Frame.h>
|
||||
#include <JsonFakeValueGenerator.h>
|
||||
#include <LinearFakeValueGenerator.h>
|
||||
@@ -27,6 +26,8 @@
|
||||
#include <TestPropertyUtils.h>
|
||||
#include <VehicleHalTypes.h>
|
||||
#include <VehicleUtils.h>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/parsedouble.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
@@ -74,9 +75,16 @@ using ::android::base::ScopedLockAssertion;
|
||||
using ::android::base::StartsWith;
|
||||
using ::android::base::StringPrintf;
|
||||
|
||||
const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
|
||||
const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";
|
||||
const char* POWER_STATE_REQ_CONFIG_PROPERTY = "ro.vendor.fake_vhal.ap_power_state_req.config";
|
||||
// The directory for default property configuration file.
|
||||
// For config file format, see impl/default_config/config/README.md.
|
||||
constexpr char DEFAULT_CONFIG_DIR[] = "/vendor/etc/automotive/vhalconfig/";
|
||||
// The directory for property configuration file that overrides the default configuration file.
|
||||
// For config file format, see impl/default_config/config/README.md.
|
||||
constexpr char OVERRIDE_CONFIG_DIR[] = "/vendor/etc/automotive/vhaloverride/";
|
||||
// If OVERRIDE_PROPERTY is set, we will use the configuration files from OVERRIDE_CONFIG_DIR to
|
||||
// overwrite the default configs.
|
||||
constexpr char OVERRIDE_PROPERTY[] = "persist.vendor.vhal_init_value_override";
|
||||
constexpr char POWER_STATE_REQ_CONFIG_PROPERTY[] = "ro.vendor.fake_vhal.ap_power_state_req.config";
|
||||
|
||||
// A list of supported options for "--set" command.
|
||||
const std::unordered_set<std::string> SET_PROP_OPTIONS = {
|
||||
@@ -139,10 +147,11 @@ void FakeVehicleHardware::storePropInitialValue(const ConfigDeclaration& config)
|
||||
}
|
||||
|
||||
FakeVehicleHardware::FakeVehicleHardware()
|
||||
: FakeVehicleHardware(std::make_unique<VehiclePropValuePool>()) {}
|
||||
: FakeVehicleHardware(DEFAULT_CONFIG_DIR, OVERRIDE_CONFIG_DIR, false) {}
|
||||
|
||||
FakeVehicleHardware::FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool)
|
||||
: mValuePool(std::move(valuePool)),
|
||||
FakeVehicleHardware::FakeVehicleHardware(std::string defaultConfigDir,
|
||||
std::string overrideConfigDir, bool forceOverride)
|
||||
: mValuePool(std::make_unique<VehiclePropValuePool>()),
|
||||
mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
|
||||
mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
|
||||
mFakeUserHal(new FakeUserHal(mValuePool)),
|
||||
@@ -150,7 +159,10 @@ FakeVehicleHardware::FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> v
|
||||
mGeneratorHub(new GeneratorHub(
|
||||
[this](const VehiclePropValue& value) { eventFromVehicleBus(value); })),
|
||||
mPendingGetValueRequests(this),
|
||||
mPendingSetValueRequests(this) {
|
||||
mPendingSetValueRequests(this),
|
||||
mDefaultConfigDir(defaultConfigDir),
|
||||
mOverrideConfigDir(overrideConfigDir),
|
||||
mForceOverride(forceOverride) {
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -160,9 +172,19 @@ FakeVehicleHardware::~FakeVehicleHardware() {
|
||||
mGeneratorHub.reset();
|
||||
}
|
||||
|
||||
std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
|
||||
std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
|
||||
loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
|
||||
if (mForceOverride ||
|
||||
android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false)) {
|
||||
loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
|
||||
}
|
||||
return configsByPropId;
|
||||
}
|
||||
|
||||
void FakeVehicleHardware::init() {
|
||||
for (auto& it : defaultconfig::getDefaultConfigs()) {
|
||||
VehiclePropConfig cfg = it.config;
|
||||
for (auto& [_, configDeclaration] : loadConfigDeclarations()) {
|
||||
VehiclePropConfig cfg = configDeclaration.config;
|
||||
VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
|
||||
|
||||
if (cfg.prop == toInt(VehicleProperty::AP_POWER_STATE_REQ)) {
|
||||
@@ -178,15 +200,18 @@ void FakeVehicleHardware::init() {
|
||||
// logic.
|
||||
continue;
|
||||
}
|
||||
storePropInitialValue(it);
|
||||
storePropInitialValue(configDeclaration);
|
||||
}
|
||||
|
||||
maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
|
||||
|
||||
// OBD2_LIVE_FRAME and OBD2_FREEZE_FRAME must be configured in default configs.
|
||||
mFakeObd2Frame->initObd2LiveFrame(*mServerSidePropStore->getConfig(OBD2_LIVE_FRAME).value());
|
||||
mFakeObd2Frame->initObd2FreezeFrame(
|
||||
*mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME).value());
|
||||
auto maybeObd2LiveFrame = mServerSidePropStore->getConfig(OBD2_LIVE_FRAME);
|
||||
if (maybeObd2LiveFrame.has_value()) {
|
||||
mFakeObd2Frame->initObd2LiveFrame(*maybeObd2LiveFrame.value());
|
||||
}
|
||||
auto maybeObd2FreezeFrame = mServerSidePropStore->getConfig(OBD2_FREEZE_FRAME);
|
||||
if (maybeObd2FreezeFrame.has_value()) {
|
||||
mFakeObd2Frame->initObd2FreezeFrame(*maybeObd2FreezeFrame.value());
|
||||
}
|
||||
|
||||
mServerSidePropStore->setOnValueChangeCallback(
|
||||
[this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
|
||||
@@ -408,7 +433,7 @@ VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValu
|
||||
*isSpecialValue = true;
|
||||
return mFakeObd2Frame->clearObd2FreezeFrames(value);
|
||||
|
||||
#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
|
||||
#ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
|
||||
case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
|
||||
[[fallthrough]];
|
||||
case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
|
||||
@@ -436,7 +461,7 @@ VhalResult<void> FakeVehicleHardware::maybeSetSpecialValue(const VehiclePropValu
|
||||
<< getErrorMsg(writeResult);
|
||||
}
|
||||
return {};
|
||||
#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
|
||||
#endif // ENABLE_VEHICLE_HAL_TEST_PROPERTIES
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -1264,33 +1289,26 @@ void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
|
||||
(*mOnPropertyChangeCallback)(std::move(updatedValues));
|
||||
}
|
||||
|
||||
void FakeVehicleHardware::maybeOverrideProperties(const char* overrideDir) {
|
||||
if (android::base::GetBoolProperty(OVERRIDE_PROPERTY, false)) {
|
||||
overrideProperties(overrideDir);
|
||||
}
|
||||
}
|
||||
|
||||
void FakeVehicleHardware::overrideProperties(const char* overrideDir) {
|
||||
ALOGI("loading vendor override properties from %s", overrideDir);
|
||||
if (auto dir = opendir(overrideDir); dir != NULL) {
|
||||
void FakeVehicleHardware::loadPropConfigsFromDir(
|
||||
const std::string& dirPath,
|
||||
std::unordered_map<int32_t, ConfigDeclaration>* configsByPropId) {
|
||||
ALOGI("loading properties from %s", dirPath.c_str());
|
||||
if (auto dir = opendir(dirPath.c_str()); dir != NULL) {
|
||||
std::regex regJson(".*[.]json", std::regex::icase);
|
||||
while (auto f = readdir(dir)) {
|
||||
if (!std::regex_match(f->d_name, regJson)) {
|
||||
continue;
|
||||
}
|
||||
std::string file = overrideDir + std::string(f->d_name);
|
||||
JsonFakeValueGenerator tmpGenerator(file);
|
||||
|
||||
std::vector<VehiclePropValue> propValues = tmpGenerator.getAllEvents();
|
||||
for (const VehiclePropValue& prop : propValues) {
|
||||
auto propToStore = mValuePool->obtain(prop);
|
||||
propToStore->timestamp = elapsedRealtimeNano();
|
||||
if (auto result = mServerSidePropStore->writeValue(std::move(propToStore),
|
||||
/*updateStatus=*/true);
|
||||
!result.ok()) {
|
||||
ALOGW("failed to write vendor override properties: %d, error: %s, code: %d",
|
||||
prop.prop, getErrorMsg(result).c_str(), getIntErrorCode(result));
|
||||
}
|
||||
std::string filePath = dirPath + "/" + std::string(f->d_name);
|
||||
ALOGI("loading properties from %s", filePath.c_str());
|
||||
auto result = mLoader.loadPropConfig(filePath);
|
||||
if (!result.ok()) {
|
||||
ALOGE("failed to load config file: %s, error: %s", filePath.c_str(),
|
||||
result.error().message().c_str());
|
||||
continue;
|
||||
}
|
||||
for (auto& [propId, configDeclaration] : result.value()) {
|
||||
(*configsByPropId)[propId] = std::move(configDeclaration);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
@@ -22,13 +22,13 @@ cc_test {
|
||||
name: "FakeVehicleHardwareTest",
|
||||
vendor: true,
|
||||
srcs: ["*.cpp"],
|
||||
cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
|
||||
cflags: ["-DENABLE_VEHICLE_HAL_TEST_PROPERTIES"],
|
||||
header_libs: [
|
||||
"IVehicleHardware",
|
||||
"VehicleHalDefaultConfig",
|
||||
"VehicleHalTestUtilHeaders",
|
||||
],
|
||||
static_libs: [
|
||||
"VehicleHalJsonConfigLoaderEnableTestProperties",
|
||||
"VehicleHalUtils",
|
||||
"FakeVehicleHardware",
|
||||
"FakeVehicleHalValueGenerators",
|
||||
@@ -41,6 +41,9 @@ cc_test {
|
||||
"libjsoncpp",
|
||||
],
|
||||
data: [
|
||||
":VehicleHalDefaultProperties_JSON",
|
||||
":VehicleHalTestProperties_JSON",
|
||||
":VehicleHalVendorClusterTestProperties_JSON",
|
||||
":FakeVehicleHardwareTestOverrideJson",
|
||||
":FakeVehicleHardwareTestPropJson",
|
||||
],
|
||||
@@ -55,5 +58,5 @@ filegroup {
|
||||
|
||||
filegroup {
|
||||
name: "FakeVehicleHardwareTestPropJson",
|
||||
srcs: ["prop.json"],
|
||||
srcs: ["fakedata/prop.json"],
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <FakeVehicleHardware.h>
|
||||
|
||||
#include <DefaultConfig.h>
|
||||
#include <FakeObd2Frame.h>
|
||||
#include <FakeUserHal.h>
|
||||
#include <PropertyUtils.h>
|
||||
@@ -80,7 +79,9 @@ class FakeVehicleHardwareTestHelper {
|
||||
public:
|
||||
FakeVehicleHardwareTestHelper(FakeVehicleHardware* hardware) { mHardware = hardware; }
|
||||
|
||||
void overrideProperties(const char* overrideDir) { mHardware->overrideProperties(overrideDir); }
|
||||
std::unordered_map<int32_t, ConfigDeclaration> loadConfigDeclarations() {
|
||||
return mHardware->loadConfigDeclarations();
|
||||
}
|
||||
|
||||
private:
|
||||
FakeVehicleHardware* mHardware;
|
||||
@@ -89,7 +90,9 @@ class FakeVehicleHardwareTestHelper {
|
||||
class FakeVehicleHardwareTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mHardware = std::make_unique<FakeVehicleHardware>();
|
||||
mHardware = std::make_unique<FakeVehicleHardware>(android::base::GetExecutableDirectory(),
|
||||
/*overrideConfigDir=*/"",
|
||||
/*forceOverride=*/false);
|
||||
auto callback = std::make_unique<IVehicleHardware::PropertyChangeCallback>(
|
||||
[this](const std::vector<VehiclePropValue>& values) {
|
||||
onPropertyChangeEvent(values);
|
||||
@@ -109,6 +112,10 @@ class FakeVehicleHardwareTest : public ::testing::Test {
|
||||
|
||||
FakeVehicleHardware* getHardware() { return mHardware.get(); }
|
||||
|
||||
void setHardware(std::unique_ptr<FakeVehicleHardware> hardware) {
|
||||
mHardware = std::move(hardware);
|
||||
}
|
||||
|
||||
StatusCode setValues(const std::vector<SetValueRequest>& requests) {
|
||||
{
|
||||
std::scoped_lock<std::mutex> lockGuard(mLock);
|
||||
@@ -374,7 +381,8 @@ class FakeVehicleHardwareTest : public ::testing::Test {
|
||||
TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
|
||||
std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();
|
||||
|
||||
ASSERT_EQ(configs.size(), defaultconfig::getDefaultConfigs().size());
|
||||
FakeVehicleHardwareTestHelper helper(getHardware());
|
||||
ASSERT_EQ(configs.size(), helper.loadConfigDeclarations().size());
|
||||
}
|
||||
|
||||
TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
|
||||
@@ -382,7 +390,8 @@ TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
|
||||
std::vector<GetValueResult> expectedGetValueResults;
|
||||
int64_t requestId = 1;
|
||||
|
||||
for (auto& config : defaultconfig::getDefaultConfigs()) {
|
||||
FakeVehicleHardwareTestHelper helper(getHardware());
|
||||
for (auto& [propId, config] : helper.loadConfigDeclarations()) {
|
||||
if (obd2frame::FakeObd2Frame::isDiagnosticProperty(config.config)) {
|
||||
// Ignore storing default value for diagnostic property. They have special get/set
|
||||
// logic.
|
||||
@@ -394,12 +403,11 @@ TEST_F(FakeVehicleHardwareTest, testGetDefaultValues) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.config.prop == ECHO_REVERSE_BYTES) {
|
||||
if (propId == ECHO_REVERSE_BYTES) {
|
||||
// Ignore ECHO_REVERSE_BYTES, it has special logic.
|
||||
continue;
|
||||
}
|
||||
|
||||
int propId = config.config.prop;
|
||||
if (isGlobalProp(propId)) {
|
||||
if (config.initialValue == RawPropValues{}) {
|
||||
addGetValueRequest(getValueRequests, expectedGetValueResults, requestId++,
|
||||
@@ -657,10 +665,12 @@ TEST_F(FakeVehicleHardwareTest, testSetStatusMustIgnore) {
|
||||
}
|
||||
|
||||
TEST_F(FakeVehicleHardwareTest, testVendorOverrideProperties) {
|
||||
std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
|
||||
std::string currentDir = android::base::GetExecutableDirectory();
|
||||
std::string overrideDir = currentDir + "/override/";
|
||||
// Set vendor override directory.
|
||||
FakeVehicleHardwareTestHelper helper(getHardware());
|
||||
helper.overrideProperties(overrideDir.c_str());
|
||||
std::unique_ptr<FakeVehicleHardware> hardware =
|
||||
std::make_unique<FakeVehicleHardware>(currentDir, overrideDir, /*forceOverride=*/true);
|
||||
setHardware(std::move(hardware));
|
||||
|
||||
// This is the same as the prop in 'gear_selection.json'.
|
||||
int gearProp = toInt(VehicleProperty::GEAR_SELECTION);
|
||||
@@ -695,10 +705,12 @@ TEST_F(FakeVehicleHardwareTest, testVendorOverrideProperties) {
|
||||
}
|
||||
|
||||
TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesMultipleAreas) {
|
||||
std::string overrideDir = android::base::GetExecutableDirectory() + "/override/";
|
||||
std::string currentDir = android::base::GetExecutableDirectory();
|
||||
std::string overrideDir = currentDir + "/override/";
|
||||
// Set vendor override directory.
|
||||
FakeVehicleHardwareTestHelper helper(getHardware());
|
||||
helper.overrideProperties(overrideDir.c_str());
|
||||
std::unique_ptr<FakeVehicleHardware> hardware =
|
||||
std::make_unique<FakeVehicleHardware>(currentDir, overrideDir, /*forceOverride=*/true);
|
||||
setHardware(std::move(hardware));
|
||||
|
||||
// This is the same as the prop in 'hvac_temperature_set.json'.
|
||||
int hvacProp = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
|
||||
@@ -711,22 +723,16 @@ TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesMultipleAreas) {
|
||||
ASSERT_TRUE(result.ok()) << "expect to get the overridden property ok: " << getStatus(result);
|
||||
ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
|
||||
ASSERT_EQ(30.0f, result.value().value.floatValues[0]);
|
||||
|
||||
// HVAC_RIGHT should not be affected and return the default value.
|
||||
result = getValue(VehiclePropValue{
|
||||
.prop = hvacProp,
|
||||
.areaId = HVAC_RIGHT,
|
||||
});
|
||||
|
||||
ASSERT_TRUE(result.ok()) << "expect to get the default property ok: " << getStatus(result);
|
||||
ASSERT_EQ(static_cast<size_t>(1), result.value().value.floatValues.size());
|
||||
ASSERT_EQ(20.0f, result.value().value.floatValues[0]);
|
||||
}
|
||||
|
||||
TEST_F(FakeVehicleHardwareTest, testVendorOverridePropertiesDirDoesNotExist) {
|
||||
// Set vendor override directory to a non-existing dir
|
||||
FakeVehicleHardwareTestHelper helper(getHardware());
|
||||
helper.overrideProperties("123");
|
||||
std::string currentDir = android::base::GetExecutableDirectory();
|
||||
std::string overrideDir = currentDir + "/override/";
|
||||
// Set vendor override directory to a non-existing dir.
|
||||
std::unique_ptr<FakeVehicleHardware> hardware =
|
||||
std::make_unique<FakeVehicleHardware>(currentDir, "1234", /*forceOverride=*/true);
|
||||
setHardware(std::move(hardware));
|
||||
|
||||
auto result = getValue(VehiclePropValue{
|
||||
.prop = toInt(VehicleProperty::GEAR_SELECTION),
|
||||
});
|
||||
@@ -1840,7 +1846,7 @@ TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataLinear) {
|
||||
|
||||
std::string getTestFilePath(const char* filename) {
|
||||
static std::string baseDir = android::base::GetExecutableDirectory();
|
||||
return baseDir + "/" + filename;
|
||||
return baseDir + "/fakedata/" + filename;
|
||||
}
|
||||
|
||||
TEST_F(FakeVehicleHardwareTest, testDebugGenFakeDataJson) {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1000000,
|
||||
"areaId": 0,
|
||||
"value": 8,
|
||||
// GEAR_SELECTION
|
||||
"prop": 289408000
|
||||
}
|
||||
]
|
||||
{
|
||||
"apiVersion": 1,
|
||||
"properties": [
|
||||
{
|
||||
"property": "VehicleProperty::GEAR_SELECTION",
|
||||
"defaultValue": {
|
||||
"int32Values": [
|
||||
8
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
[
|
||||
{
|
||||
"timestamp": 1000000,
|
||||
// HVAC_LEFT
|
||||
"areaId": 49,
|
||||
"value": 30,
|
||||
// HVAC_TEMPERATURE_SET
|
||||
"prop": 358614275
|
||||
}
|
||||
]
|
||||
{
|
||||
"apiVersion": 1,
|
||||
"properties": [
|
||||
{
|
||||
"property": "VehicleProperty::HVAC_TEMPERATURE_SET",
|
||||
"areas": [
|
||||
{
|
||||
"defaultValue": {
|
||||
"floatValues": [
|
||||
30.0
|
||||
]
|
||||
},
|
||||
"areaId": 49,
|
||||
"minFloatValue": 16.0,
|
||||
"maxFloatValue": 32.0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -47,13 +47,20 @@ cc_test {
|
||||
],
|
||||
vendor: true,
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
shared_libs: ["libprotobuf-cpp-full"],
|
||||
shared_libs: [
|
||||
"libprotobuf-cpp-full",
|
||||
"libjsoncpp",
|
||||
],
|
||||
static_libs: [
|
||||
"VehicleHalJsonConfigLoaderEnableTestProperties",
|
||||
"VehicleHalProtoMessageConverter",
|
||||
"VehicleHalProtos",
|
||||
"VehicleHalUtils",
|
||||
"libgtest",
|
||||
],
|
||||
data: [
|
||||
":VehicleHalDefaultProperties_JSON",
|
||||
],
|
||||
header_libs: ["VehicleHalDefaultConfig"],
|
||||
test_suites: ["device-tests"],
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <DefaultConfig.h>
|
||||
#include <JsonConfigLoader.h>
|
||||
#include <ProtoMessageConverter.h>
|
||||
#include <VehicleHalTypes.h>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/format.h>
|
||||
#include <android/hardware/automotive/vehicle/VehiclePropConfig.pb.h>
|
||||
#include <android/hardware/automotive/vehicle/VehiclePropValue.pb.h>
|
||||
@@ -35,23 +37,39 @@ namespace {
|
||||
namespace proto = ::android::hardware::automotive::vehicle::proto;
|
||||
namespace aidl_vehicle = ::aidl::android::hardware::automotive::vehicle;
|
||||
|
||||
constexpr char DEFAULT_PROPERTIES_CONFIG[] = "DefaultProperties.json";
|
||||
|
||||
inline std::string getConfigPath(const std::string& name) {
|
||||
return android::base::GetExecutableDirectory() + "/" + name;
|
||||
}
|
||||
|
||||
std::vector<aidl_vehicle::VehiclePropConfig> prepareTestConfigs() {
|
||||
JsonConfigLoader loader;
|
||||
auto result = loader.loadPropConfig(getConfigPath(DEFAULT_PROPERTIES_CONFIG));
|
||||
if (!result.ok()) {
|
||||
return {};
|
||||
}
|
||||
std::vector<aidl_vehicle::VehiclePropConfig> configs;
|
||||
for (auto& property : defaultconfig::getDefaultConfigs()) {
|
||||
configs.push_back(property.config);
|
||||
for (auto& [_, configDeclaration] : result.value()) {
|
||||
configs.push_back(configDeclaration.config);
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
std::vector<aidl_vehicle::VehiclePropValue> prepareTestValues() {
|
||||
JsonConfigLoader loader;
|
||||
auto result = loader.loadPropConfig(getConfigPath(DEFAULT_PROPERTIES_CONFIG));
|
||||
if (!result.ok()) {
|
||||
return {};
|
||||
}
|
||||
std::vector<aidl_vehicle::VehiclePropValue> values;
|
||||
int64_t timestamp = 1;
|
||||
for (auto& property : defaultconfig::getDefaultConfigs()) {
|
||||
for (auto& [_, configDeclaration] : result.value()) {
|
||||
values.push_back({
|
||||
.timestamp = timestamp,
|
||||
.areaId = 123,
|
||||
.prop = property.config.prop,
|
||||
.value = property.initialValue,
|
||||
.prop = configDeclaration.config.prop,
|
||||
.value = configDeclaration.initialValue,
|
||||
.status = aidl_vehicle::VehiclePropertyStatus::ERROR,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,10 +75,6 @@ cc_fuzz {
|
||||
"VehicleHalDefaults",
|
||||
"android-automotive-large-parcelable-defaults",
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleHardware",
|
||||
"VehicleHalDefaultConfig",
|
||||
],
|
||||
static_libs: [
|
||||
"DefaultVehicleHal",
|
||||
"FakeVehicleHardware",
|
||||
|
||||
Reference in New Issue
Block a user