Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b64b82f authored by Yu Shan's avatar Yu Shan
Browse files

Add area config parsing.

Add area config parsing to JsonConfigLoader.

Test: atest JsonConfigLoaderUnitTestEnableTestProperties
atest VehicleHalDefaultConfigTestEnableTestProperties
Bug: 238685398

Change-Id: I22c1b54fb5463b6c747645293ed47c5799d5f262
parent 61dd7a76
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -542,7 +542,7 @@ enum VehicleProperty {
     */
    TRACTION_CONTROL_ACTIVE = 0x040B + 0x10000000 + 0x01000000
            + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
    /*
    /**
     * HVAC Properties
     *
     * Additional rules for mapping a zoned HVAC property (except
+7 −1
Original line number Diff line number Diff line
@@ -137,9 +137,15 @@ class JsonConfigParser {
            T* outPtr, std::vector<std::string>* errors);

    // Parses a JSON field to RawPropValues.
    void parsePropValues(const Json::Value& parentJsonNode, const std::string& fieldName,
    //
    // @return True if the field exist and can be parsed to a RawPropValues.
    bool parsePropValues(const Json::Value& parentJsonNode, const std::string& fieldName,
                         aidl::android::hardware::automotive::vehicle::RawPropValues* outPtr,
                         std::vector<std::string>* errors);

    // Prase a JSON field as an array of area configs.
    void parseAreas(const Json::Value& parentJsonNode, const std::string& fieldName,
                    ConfigDeclaration* outPtr, std::vector<std::string>* errors);
};

}  // namespace jsonconfigloader_impl
+59 −13
Original line number Diff line number Diff line
@@ -398,9 +398,32 @@ void JsonConfigParser::parseAccessChangeMode(
    return;
}

void JsonConfigParser::parsePropValues(const Json::Value& parentJsonNode,
bool JsonConfigParser::parsePropValues(const Json::Value& parentJsonNode,
                                       const std::string& fieldName, RawPropValues* outPtr,
                                       std::vector<std::string>* errors) {
    if (!parentJsonNode.isObject()) {
        errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
        return false;
    }
    if (!parentJsonNode.isMember(fieldName)) {
        return false;
    }
    const Json::Value& jsonValue = parentJsonNode[fieldName];
    bool success = true;
    success &= tryParseJsonArrayToVariable(jsonValue, "int32Values",
                                           /*optional=*/true, &(outPtr->int32Values), errors);
    success &= tryParseJsonArrayToVariable(jsonValue, "floatValues",
                                           /*optional=*/true, &(outPtr->floatValues), errors);
    success &= tryParseJsonArrayToVariable(jsonValue, "int64Values",
                                           /*optional=*/true, &(outPtr->int64Values), errors);
    // We don't support "byteValues" yet.
    success &= tryParseJsonValueToVariable(jsonValue, "stringValue",
                                           /*optional=*/true, &(outPtr->stringValue), errors);
    return success;
}

void JsonConfigParser::parseAreas(const Json::Value& parentJsonNode, const std::string& fieldName,
                                  ConfigDeclaration* config, std::vector<std::string>* errors) {
    if (!parentJsonNode.isObject()) {
        errors->push_back("Node: " + parentJsonNode.toStyledString() + " is not an object");
        return;
@@ -409,15 +432,39 @@ void JsonConfigParser::parsePropValues(const Json::Value& parentJsonNode,
        return;
    }
    const Json::Value& jsonValue = parentJsonNode[fieldName];
    tryParseJsonArrayToVariable(jsonValue, "int32Values", /*optional=*/true, &(outPtr->int32Values),
                                errors);
    tryParseJsonArrayToVariable(jsonValue, "floatValues", /*optional=*/true, &(outPtr->floatValues),
                                errors);
    tryParseJsonArrayToVariable(jsonValue, "int64Values", /*optional=*/true, &(outPtr->int64Values),
                                errors);
    // We don't support "byteValues" yet.
    tryParseJsonValueToVariable(jsonValue, "stringValue", /*optional=*/true, &(outPtr->stringValue),
                                errors);

    if (!jsonValue.isArray()) {
        errors->push_back("Field: " + fieldName + " is not an array");
        return;
    }
    for (unsigned int i = 0; i < jsonValue.size(); i++) {
        int32_t areaId;
        const Json::Value& jsonAreaConfig = jsonValue[i];
        if (!tryParseJsonValueToVariable(jsonAreaConfig, "areaId",
                                         /*optional=*/false, &areaId, errors)) {
            continue;
        }
        VehicleAreaConfig areaConfig = {};
        areaConfig.areaId = areaId;
        tryParseJsonValueToVariable(jsonAreaConfig, "minInt32Value", /*optional=*/true,
                                    &areaConfig.minInt32Value, errors);
        tryParseJsonValueToVariable(jsonAreaConfig, "maxInt32Value", /*optional=*/true,
                                    &areaConfig.maxInt32Value, errors);
        tryParseJsonValueToVariable(jsonAreaConfig, "minInt64Value", /*optional=*/true,
                                    &areaConfig.minInt64Value, errors);
        tryParseJsonValueToVariable(jsonAreaConfig, "maxInt64Value", /*optional=*/true,
                                    &areaConfig.maxInt64Value, errors);
        tryParseJsonValueToVariable(jsonAreaConfig, "minFloatValue", /*optional=*/true,
                                    &areaConfig.minFloatValue, errors);
        tryParseJsonValueToVariable(jsonAreaConfig, "maxFloatValue", /*optional=*/true,
                                    &areaConfig.maxFloatValue, errors);
        config->config.areaConfigs.push_back(std::move(areaConfig));

        RawPropValues areaValue = {};
        if (parsePropValues(jsonAreaConfig, "defaultValue", &areaValue, errors)) {
            config->initialAreaValues[areaId] = std::move(areaValue);
        }
    }
}

std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
@@ -446,8 +493,7 @@ std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
    tryParseJsonArrayToVariable(propJsonValue, "configArray", /*optional=*/true,
                                &configDecl.config.configArray, errors);

    parsePropValues(propJsonValue, "defaultValue", /*optional=*/true, &configDecl.initialValue,
                    errors);
    parsePropValues(propJsonValue, "defaultValue", &configDecl.initialValue, errors);

    tryParseJsonValueToVariable(propJsonValue, "minSampleRate", /*optional=*/true,
                                &configDecl.config.minSampleRate, errors);
@@ -455,7 +501,7 @@ std::optional<ConfigDeclaration> JsonConfigParser::parseEachProperty(
    tryParseJsonValueToVariable(propJsonValue, "maxSampleRate", /*optional=*/true,
                                &configDecl.config.maxSampleRate, errors);

    // TODO(b/238685398): AreaConfigs
    parseAreas(propJsonValue, "areas", &configDecl, errors);

    if (errors->size() != initialErrorCount) {
        return std::nullopt;
+88 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ namespace automotive {
namespace vehicle {

using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
@@ -108,7 +109,7 @@ TEST_F(JsonConfigLoaderUnitTest, TestProperty_FailInvalidJson) {
    }
    )");

    ASSERT_FALSE(mLoader.loadPropConfig(iss);.ok()) << "Invalid JSON format must cause error";
    ASSERT_FALSE(mLoader.loadPropConfig(iss).ok()) << "Invalid JSON format must cause error";
}

TEST_F(JsonConfigLoaderUnitTest, TestConfigArray) {
@@ -490,9 +491,9 @@ TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_FailInvalidType) {
    {
        "properties": [{
            "property": "VehicleProperty::INFO_FUEL_CAPACITY",
            "defaultValue": [{
            "defaultValue": {
                "int32Values": [1.1]
            }]
            }
        }]
    }
    )");
@@ -501,6 +502,90 @@ TEST_F(JsonConfigLoaderUnitTest, TestDefaultValue_FailInvalidType) {
            << "Wrong type for DefaultValue must cause error";
}

TEST_F(JsonConfigLoaderUnitTest, testAreas_Simple) {
    std::istringstream iss(R"(
    {
        "properties": [{
            "property": "VehicleProperty::INFO_FUEL_CAPACITY",
            "areas": [{
                "areaId": "Constants::HVAC_ALL",
                "minInt32Value": 1,
                "maxInt32Value": 7
            }]
        }]
    }
    )");

    auto result = mLoader.loadPropConfig(iss);

    auto configs = result.value();
    ASSERT_EQ(configs.size(), 1u);

    const VehiclePropConfig& config = configs[0].config;
    ASSERT_EQ(config.areaConfigs.size(), 1u);
    const VehicleAreaConfig& areaConfig = config.areaConfigs[0];
    ASSERT_EQ(areaConfig.minInt32Value, 1);
    ASSERT_EQ(areaConfig.maxInt32Value, 7);
    ASSERT_EQ(areaConfig.areaId, HVAC_ALL);
}

TEST_F(JsonConfigLoaderUnitTest, testAreas_DefaultValueForEachArea) {
    std::istringstream iss(R"(
    {
        "properties": [{
            "property": "VehicleProperty::INFO_FUEL_CAPACITY",
            "areas": [{
                "areaId": "Constants::HVAC_LEFT",
                "defaultValue": {
                    "int32Values": [1]
                }
            }, {
                "areaId": "Constants::HVAC_RIGHT",
                "defaultValue": {
                    "int32Values": [2]
                }
            }]
        }]
    }
    )");

    auto result = mLoader.loadPropConfig(iss);

    auto configs = result.value();
    ASSERT_EQ(configs.size(), 1u);

    const VehiclePropConfig& config = configs[0].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}});
}

TEST_F(JsonConfigLoaderUnitTest, testAreas_FailInvalidTypeForOneAreaValue) {
    std::istringstream iss(R"(
    {
        "properties": [{
            "property": "VehicleProperty::INFO_FUEL_CAPACITY",
            "areas": [{
                "areaId": "Constants::HVAC_LEFT",
                "defaultValue": {
                    "int32Values": [1]
                }
            }, {
                "areaId": "Constants::HVAC_RIGHT",
                "defaultValue": {
                    "int32Values": [2.1]
                }
            }]
        }]
    }
    )");

    ASSERT_FALSE(mLoader.loadPropConfig(iss).ok())
            << "Wrong type for DefaultValue for one area must cause error";
}

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
+1 −2
Original line number Diff line number Diff line
@@ -93,8 +93,7 @@ TEST(DefaultConfigTest, TestCompatibleWithDefaultConfigHeader) {
    }

    ASSERT_EQ(configsFromHeaderFile.size(), configsFromJson.size());
    // TODO(b/238685398): Uncomment this once we finish the parser.
    // ASSERT_THAT(configsFromHeaderFile, UnorderedElementsAreArray(configsFromJson));
    ASSERT_THAT(configsFromHeaderFile, UnorderedElementsAreArray(configsFromJson));
}

#endif  // ENABLE_VEHICLE_HAL_TEST_PROPERTIES