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

Commit 3b0b9b26 authored by Yu Shan's avatar Yu Shan
Browse files

Allow using area name in debug command.

Allow using area name instead of area ID in debug commands. Also
support AREA_1 | AREA_2 syntax. We will check the area according
to the area type specified for the property ID.

Flag: EXEMPT HAL
Test: atest FakeVehicleHardwareTest
Bug: 328316981
Change-Id: I646b76b302e58c2d0ec0ff66740da3394df62b2a
parent b02b7729
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -327,6 +327,8 @@ class FakeVehicleHardware : public IVehicleHardware {
    static android::base::Result<float> safelyParseFloat(int index, const std::string& s);
    static android::base::Result<int32_t> parsePropId(const std::vector<std::string>& options,
                                                      size_t index);
    static android::base::Result<int32_t> parseAreaId(const std::vector<std::string>& options,
                                                      size_t index, int32_t propId);
};

}  // namespace fake
+44 −7
Original line number Diff line number Diff line
@@ -1902,6 +1902,37 @@ Result<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>&
    return safelyParseInt<int32_t>(index, propIdStr);
}

// Parses areaId option ("-a"). It can be an Integer or a string in the form of "AREA_1" or
// "AREA_1 | AREA_2 | ..."
Result<int32_t> FakeVehicleHardware::parseAreaId(const std::vector<std::string>& options,
                                                 size_t index, int32_t propId) {
    const std::string& areaIdStr = options[index];
    auto result = safelyParseInt<int32_t>(index, areaIdStr);
    if (result.ok()) {
        return result;
    }

    // Check for pattern matching "AREA_1 | AREA_2 | AREA_3".
    std::regex pattern(R"(^\w+(?:( )?\|( )?\w+)*$)");
    std::smatch match;
    int32_t areaId = 0;
    if (!std::regex_match(areaIdStr, match, pattern)) {
        return result;
    }
    pattern = R"(\w+)";

    std::sregex_iterator end;
    for (std::sregex_iterator it(areaIdStr.begin(), areaIdStr.end(), pattern); it != end; it++) {
        // Parse each areas contained in this areaId.
        auto result = stringToArea(it->str(), propId);
        if (!result.ok()) {
            return result;
        }
        areaId |= result.value();
    }
    return areaId;
}

std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
    if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
        return getErrorMsg(result);
@@ -1958,6 +1989,7 @@ Result<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
    prop.status = VehiclePropertyStatus::AVAILABLE;
    optionIndex++;
    std::unordered_set<std::string> parsedOptions;
    int32_t areaIdIndex = -1;

    while (optionIndex < options.size()) {
        std::string argType = options[optionIndex];
@@ -2032,13 +2064,7 @@ Result<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
            if (argValuesSize != 1) {
                return Error() << "Expect exact one value when using \"-a\"\n";
            }
            auto int32Result = safelyParseInt<int32_t>(currentIndex, argValues[0]);
            if (!int32Result.ok()) {
                return Error() << StringPrintf("Area ID: \"%s\" is not a valid int: %s\n",
                                               argValues[0].c_str(),
                                               getErrorMsg(int32Result).c_str());
            }
            prop.areaId = int32Result.value();
            areaIdIndex = currentIndex;
        } else if (EqualsIgnoreCase(argType, "-t")) {
            if (argValuesSize != 1) {
                return Error() << "Expect exact one value when using \"-t\"\n";
@@ -2055,6 +2081,17 @@ Result<VehiclePropValue> FakeVehicleHardware::parsePropOptions(
        }
    }

    if (areaIdIndex != -1) {
        auto int32Result = parseAreaId(options, areaIdIndex, prop.prop);
        if (!int32Result.ok()) {
            return Error() << StringPrintf(
                           "Area ID: \"%s\" is not a valid int or "
                           "one or more area names: %s\n",
                           options[areaIdIndex].c_str(), getErrorMsg(int32Result).c_str());
        }
        prop.areaId = int32Result.value();
    }

    return prop;
}

+91 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReq;
using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateShutdownParam;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat;
using ::aidl::android::hardware::automotive::vehicle::VehicleHwKeyInputAction;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
@@ -2781,6 +2782,8 @@ TEST_P(FakeVehicleHardwareSetPropTest, cmdSetOneProperty) {

std::vector<SetPropTestCase> GenSetPropParams() {
    std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
    std::string testVendorProperty =
            std::to_string(toInt(TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY));
    return {
            {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true},
            {"success_set_with_name", {"--set", "INFO_MAKE", "-s", CAR_MAKE}, true},
@@ -2889,6 +2892,14 @@ std::vector<SetPropTestCase> GenSetPropParams() {
             {"--set", infoMakeProperty, "-a", "-s", CAR_MAKE},
             false,
             "Expect exact one value"},
            {"fail_invalid_area_name",
             {"--set", testVendorProperty, "-a", "ROW_1_LEFT|NO_SUCH_AREA", "-f", "1.234"},
             false,
             "not a valid int or one or more area names"},
            {"fail_invalid_area_format",
             {"--set", testVendorProperty, "-a", "ROW_1_LEFT|||ROW_2_LEFT", "-f", "1.234"},
             false,
             "not a valid int or one or more area names"},
    };
}

@@ -2933,6 +2944,86 @@ TEST_F(FakeVehicleHardwareTest, SetComplexPropTest) {
    ASSERT_EQ(3.402823466E+38f, value.value.floatValues[2]);
}

TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameAreaId) {
    int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT);
    getHardware()->dump(
            {"--set", "HVAC_TEMPERATURE_SET", "-a", std::to_string(areaId), "-f", "22.345"});

    VehiclePropValue requestProp;
    requestProp.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
    requestProp.areaId = areaId;
    auto result = getValue(requestProp);

    ASSERT_TRUE(result.ok());
    VehiclePropValue value = result.value();
    ASSERT_EQ(value.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
    ASSERT_EQ(value.areaId, areaId);
    ASSERT_EQ(1u, value.value.floatValues.size());
    ASSERT_EQ(22.345f, value.value.floatValues[0]);
}

TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameAreaName) {
    int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT);
    getHardware()->dump({"--set", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT", "-f", "22.345"});

    VehiclePropValue requestProp;
    requestProp.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET);
    requestProp.areaId = areaId;
    auto result = getValue(requestProp);

    ASSERT_TRUE(result.ok());
    VehiclePropValue value = result.value();
    ASSERT_EQ(value.prop, toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
    ASSERT_EQ(value.areaId, areaId);
    ASSERT_EQ(1u, value.value.floatValues.size());
    ASSERT_EQ(22.345f, value.value.floatValues[0]);
}

TEST_F(FakeVehicleHardwareTest, GetPropertyWithPropertyNameAreaName) {
    auto result = getHardware()->dump({"--get", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT"});

    // Default value is 17
    ASSERT_THAT(result.buffer, ContainsRegex("17"));

    getHardware()->dump({"--set", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT", "-f", "22"});
    result = getHardware()->dump({"--get", "HVAC_TEMPERATURE_SET", "-a", "ROW_1_LEFT"});

    ASSERT_THAT(result.buffer, ContainsRegex("22"));
}

TEST_F(FakeVehicleHardwareTest, SetPropertyWithPropertyNameTwoAreasInOneId) {
    int32_t propId = toInt(TestVendorProperty::VENDOR_EXTENSION_FLOAT_PROPERTY);
    std::string testVendorProperty = std::to_string(propId);
    getHardware()->dump({"--set", testVendorProperty, "-a", "ROW_1_LEFT|ROW_2_LEFT|ROW_2_CENTER",
                         "-f", "1.234"});

    VehiclePropValue requestProp;
    requestProp.prop = propId;
    int32_t areaId = toInt(VehicleAreaSeat::ROW_1_LEFT) | toInt(VehicleAreaSeat::ROW_2_LEFT) |
                     toInt(VehicleAreaSeat::ROW_2_CENTER);
    requestProp.areaId = areaId;
    auto result = getValue(requestProp);

    ASSERT_TRUE(result.ok());
    VehiclePropValue value = result.value();
    ASSERT_EQ(value.prop, propId);
    ASSERT_EQ(value.areaId, areaId);
    ASSERT_EQ(1u, value.value.floatValues.size());
    ASSERT_EQ(1.234f, value.value.floatValues[0]);

    // Ignore space between two areas.
    getHardware()->dump({"--set", testVendorProperty, "-a",
                         "ROW_1_LEFT | ROW_2_LEFT | ROW_2_CENTER", "-f", "2.345"});
    result = getValue(requestProp);

    ASSERT_TRUE(result.ok());
    value = result.value();
    ASSERT_EQ(value.prop, propId);
    ASSERT_EQ(value.areaId, areaId);
    ASSERT_EQ(1u, value.value.floatValues.size());
    ASSERT_EQ(2.345f, value.value.floatValues[0]);
}

struct OptionsTestCase {
    std::string name;
    std::vector<std::string> options;
+3 −0
Original line number Diff line number Diff line
@@ -337,6 +337,9 @@ inline std::string propIdToString(int32_t propId) {
// This is for debug purpose only.
android::base::Result<int32_t> stringToPropId(const std::string& propName);

// This is for debug purpose only. Converts an area's name to its enum definition.
android::base::Result<int32_t> stringToArea(const std::string& areaName, int32_t propId);

template <typename T>
void roundToNearestResolution(std::vector<T>& arrayToSanitize, float resolution) {
    if (resolution == 0) {
+57 −1
Original line number Diff line number Diff line
@@ -25,7 +25,13 @@ namespace vehicle {

using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::toString;
using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaDoor;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaMirror;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaSeat;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWheel;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
@@ -44,7 +50,7 @@ class PropertyIdByNameSingleton {
        return instance;
    }

    Result<int32_t> getPropertyId(const std::string& name) {
    Result<int32_t> getPropertyId(const std::string& name) const {
        auto it = mPropertyIdByName.find(name);
        if (it == mPropertyIdByName.end()) {
            return Error();
@@ -66,6 +72,52 @@ class PropertyIdByNameSingleton {
    }
};

class AreaByNameSingleton {
  public:
    static AreaByNameSingleton& getInstance() {
        static AreaByNameSingleton instance;
        return instance;
    }

    Result<int32_t> getArea(const std::string& name, int32_t propId) const {
        VehicleArea areaType = getPropArea(propId);

        auto mapIt = mAreaByNameByAreaType.find(areaType);
        if (mapIt == mAreaByNameByAreaType.end()) {
            return Error() << "Invalid area type for property ID: " << propIdToString(propId);
        }

        const auto& areaByName = mapIt->second;
        auto it = areaByName.find(name);
        if (it == areaByName.end()) {
            return Error() << "Invalid area name for property " << propIdToString(propId) << ": "
                           << name;
        }
        return it->second;
    }

    AreaByNameSingleton(AreaByNameSingleton const&) = delete;
    void operator=(AreaByNameSingleton const&) = delete;

  private:
    std::unordered_map<VehicleArea, std::unordered_map<std::string, int32_t>> mAreaByNameByAreaType;

    AreaByNameSingleton() {
        populateMap(VehicleArea::WINDOW, ndk::internal::enum_values<VehicleAreaWindow>);
        populateMap(VehicleArea::MIRROR, ndk::internal::enum_values<VehicleAreaMirror>);
        populateMap(VehicleArea::SEAT, ndk::internal::enum_values<VehicleAreaSeat>);
        populateMap(VehicleArea::DOOR, ndk::internal::enum_values<VehicleAreaDoor>);
        populateMap(VehicleArea::WHEEL, ndk::internal::enum_values<VehicleAreaWheel>);
    }

    template <class T, std::size_t N>
    void populateMap(VehicleArea areaType, std::array<T, N> values) {
        for (unsigned int i = 0; i < values.size(); i++) {
            mAreaByNameByAreaType[areaType].emplace(toString(values[i]), toInt(values[i]));
        }
    }
};

}  // namespace

Result<void> checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) {
@@ -254,6 +306,10 @@ Result<int32_t> stringToPropId(const std::string& propName) {
    return PropertyIdByNameSingleton::getInstance().getPropertyId(propName);
}

Result<int32_t> stringToArea(const std::string& areaName, int32_t propId) {
    return AreaByNameSingleton::getInstance().getArea(areaName, propId);
}

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware