Merge "Allow using area name in debug command." into main

This commit is contained in:
Treehugger Robot
2024-06-26 02:41:39 +00:00
committed by Gerrit Code Review
5 changed files with 197 additions and 8 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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