Allow using property name in debug command. am: 2558bf60c4

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/3098460

Change-Id: I0cb9e49994a8280b6c4c7ec86e1b272a6d805950
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
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 583e40b..79d3e77 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -269,16 +269,6 @@
     std::string dumpInjectEvent(const std::vector<std::string>& options);
     std::string dumpSubscriptions();
 
-    template <typename T>
-    android::base::Result<T> safelyParseInt(int index, const std::string& s) {
-        T out;
-        if (!::android::base::ParseInt(s, &out)) {
-            return android::base::Error() << android::base::StringPrintf(
-                           "non-integer argument at index %d: %s\n", index, s.c_str());
-        }
-        return out;
-    }
-    android::base::Result<float> safelyParseFloat(int index, const std::string& s);
     std::vector<std::string> getOptionValues(const std::vector<std::string>& options,
                                              size_t* index);
     android::base::Result<aidl::android::hardware::automotive::vehicle::VehiclePropValue>
@@ -325,6 +315,18 @@
             const aidl::android::hardware::automotive::vehicle::VehiclePropConfig&
                     vehiclePropConfig,
             int32_t areaId);
+    template <typename T>
+    static android::base::Result<T> safelyParseInt(int index, const std::string& s) {
+        T out;
+        if (!::android::base::ParseInt(s, &out)) {
+            return android::base::Error() << android::base::StringPrintf(
+                           "non-integer argument at index %d: %s\n", index, s.c_str());
+        }
+        return out;
+    }
+    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);
 };
 
 }  // 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 e057d3d..200e3d3 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -1892,6 +1892,16 @@
                                    minSize, size);
 }
 
+Result<int32_t> FakeVehicleHardware::parsePropId(const std::vector<std::string>& options,
+                                                 size_t index) {
+    const std::string& propIdStr = options[index];
+    auto result = stringToPropId(propIdStr);
+    if (result.ok()) {
+        return result;
+    }
+    return safelyParseInt<int32_t>(index, propIdStr);
+}
+
 std::string FakeVehicleHardware::dumpSpecificProperty(const std::vector<std::string>& options) {
     if (auto result = checkArgumentsSize(options, /*minSize=*/2); !result.ok()) {
         return getErrorMsg(result);
@@ -1902,7 +1912,7 @@
     size_t size = options.size();
     std::string msg = "";
     for (size_t i = 1; i < size; ++i) {
-        auto propResult = safelyParseInt<int32_t>(i, options[i]);
+        auto propResult = parsePropId(options, i);
         if (!propResult.ok()) {
             msg += getErrorMsg(propResult);
             continue;
@@ -1938,9 +1948,9 @@
     // --set/get/inject-event PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...]
     // [-b b1 b2...] [-a a] [-t timestamp]
     size_t optionIndex = 1;
-    auto result = safelyParseInt<int32_t>(optionIndex, options[optionIndex]);
+    auto result = parsePropId(options, optionIndex);
     if (!result.ok()) {
-        return Error() << StringPrintf("Property value: \"%s\" is not a valid int: %s\n",
+        return Error() << StringPrintf("Property ID/Name: \"%s\" is not valid: %s\n",
                                        options[optionIndex].c_str(), getErrorMsg(result).c_str());
     }
     VehiclePropValue 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 cab33e1..0924360 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -2613,6 +2613,23 @@
                                            prop1.c_str(), prop2.c_str(), prop2.c_str())));
 }
 
+TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesWithName) {
+    std::vector<std::string> options;
+    options.push_back("--get");
+    std::string prop1 = "INFO_FUEL_CAPACITY";
+    std::string prop2 = "TIRE_PRESSURE";
+    int prop1Int = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+    int prop2Int = toInt(VehicleProperty::TIRE_PRESSURE);
+    options.push_back(prop1);
+    options.push_back(prop2);
+    DumpResult result = getHardware()->dump(options);
+    ASSERT_FALSE(result.callerShouldDumpState);
+    ASSERT_NE(result.buffer, "");
+    ASSERT_THAT(result.buffer,
+                ContainsRegex(StringPrintf("1:.*prop: %d.*\n2-0:.*prop: %d.*\n2-1:.*prop: %d.*\n",
+                                           prop1Int, prop2Int, prop2Int)));
+}
+
 TEST_F(FakeVehicleHardwareTest, testDumpSpecificPropertiesInvalidProp) {
     std::vector<std::string> options;
     options.push_back("--get");
@@ -2766,6 +2783,7 @@
     std::string infoMakeProperty = std::to_string(toInt(VehicleProperty::INFO_MAKE));
     return {
             {"success_set_string", {"--set", infoMakeProperty, "-s", CAR_MAKE}, true},
+            {"success_set_with_name", {"--set", "INFO_MAKE", "-s", CAR_MAKE}, true},
             {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
             {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
             {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
@@ -2790,10 +2808,7 @@
              false,
              "No values specified"},
             {"fail_unknown_options", {"--set", infoMakeProperty, "-abcd"}, false, "Unknown option"},
-            {"fail_invalid_property",
-             {"--set", "not valid", "-s", CAR_MAKE},
-             false,
-             "not a valid int"},
+            {"fail_invalid_property", {"--set", "not_valid", "-s", CAR_MAKE}, false, "not valid"},
             {"fail_duplicate_string",
              {"--set", infoMakeProperty, "-s", CAR_MAKE, "-s", CAR_MAKE},
              false,
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index aca725d..f48bb2a 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -328,11 +328,15 @@
     }
 };
 
+// This is for debug purpose only.
 inline std::string propIdToString(int32_t propId) {
     return toString(
             static_cast<aidl::android::hardware::automotive::vehicle::VehicleProperty>(propId));
 }
 
+// This is for debug purpose only.
+android::base::Result<int32_t> stringToPropId(const std::string& propName);
+
 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 f85728d..4d06e4e 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
@@ -16,14 +16,18 @@
 
 #include "VehicleUtils.h"
 
+#include <unordered_map>
+
 namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
 
 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::toString;
 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::VehiclePropertyGroup;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
@@ -31,6 +35,39 @@
 using ::android::base::Result;
 using ::ndk::ScopedAStatus;
 
+namespace {
+
+class PropertyIdByNameSingleton {
+  public:
+    static PropertyIdByNameSingleton& getInstance() {
+        static PropertyIdByNameSingleton instance;
+        return instance;
+    }
+
+    Result<int32_t> getPropertyId(const std::string& name) {
+        auto it = mPropertyIdByName.find(name);
+        if (it == mPropertyIdByName.end()) {
+            return Error();
+        }
+        return it->second;
+    }
+
+    PropertyIdByNameSingleton(PropertyIdByNameSingleton const&) = delete;
+    void operator=(PropertyIdByNameSingleton const&) = delete;
+
+  private:
+    std::unordered_map<std::string, int32_t> mPropertyIdByName;
+
+    PropertyIdByNameSingleton() {
+        constexpr auto values = ndk::internal::enum_values<VehicleProperty>;
+        for (unsigned int i = 0; i < values.size(); i++) {
+            mPropertyIdByName.emplace(toString(values[i]), toInt(values[i]));
+        }
+    }
+};
+
+}  // namespace
+
 Result<void> checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) {
     int32_t property = value.prop;
     VehiclePropertyType type = getPropType(property);
@@ -213,6 +250,10 @@
     return aidl::android::hardware::automotive::vehicle::toString(mCode);
 }
 
+Result<int32_t> stringToPropId(const std::string& propName) {
+    return PropertyIdByNameSingleton::getInstance().getPropertyId(propName);
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index 9abb2a2..1048877 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -770,6 +770,23 @@
     ASSERT_EQ(result.error().message(), "error message: INVALID_ARG");
 }
 
+TEST(VehicleUtilsTest, testPropIdToString) {
+    ASSERT_EQ(propIdToString(toInt(VehicleProperty::PERF_VEHICLE_SPEED)), "PERF_VEHICLE_SPEED");
+}
+
+TEST(VehicleUtilsTest, testStringToPropId) {
+    auto result = stringToPropId("PERF_VEHICLE_SPEED");
+
+    ASSERT_TRUE(result.ok());
+    ASSERT_EQ(result.value(), toInt(VehicleProperty::PERF_VEHICLE_SPEED));
+}
+
+TEST(VehicleUtilsTest, testStringToPropId_InvalidName) {
+    auto result = stringToPropId("PERF_VEHICLE_SPEED12345");
+
+    ASSERT_FALSE(result.ok());
+}
+
 class InvalidPropValueTest : public testing::TestWithParam<InvalidPropValueTestCase> {};
 
 INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest,