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
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 79d3e77..ec69894 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -327,6 +327,8 @@
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
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 200e3d3..237a4c4 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -1902,6 +1902,37 @@
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 @@
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 @@
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 @@
}
}
+ 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;
}
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 0924360..8dbba19 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -77,6 +77,7 @@
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 @@
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 @@
{"--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 @@
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;
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index f48bb2a..90a7c46 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -337,6 +337,9 @@
// 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) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
index 4d06e4e..7814c99 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
@@ -25,7 +25,13 @@
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 @@
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 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 @@
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