Merge "aconfig: add list_flag api cxx interlop" into main
diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
index 548078f..7af024b 100644
--- a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
+++ b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
@@ -7,6 +7,29 @@
 
 namespace aconfig_storage {
 
+Result<std::vector<FlagValueSummary>> list_flags(
+    const std::string& package_map,
+    const std::string& flag_map,
+    const std::string& flag_val) {
+  auto flag_list_cxx = list_flags_cxx(rust::Str(package_map.c_str()),
+                                      rust::Str(flag_map.c_str()),
+                                      rust::Str(flag_val.c_str()));
+  if (flag_list_cxx.query_success) {
+    auto flag_list = std::vector<FlagValueSummary>();
+    for (const auto& flag_cxx : flag_list_cxx.flags) {
+      auto flag = FlagValueSummary();
+      flag.package_name = std::string(flag_cxx.package_name);
+      flag.flag_name = std::string(flag_cxx.flag_name);
+      flag.flag_value = std::string(flag_cxx.flag_value);
+      flag.value_type = std::string(flag_cxx.value_type);
+      flag_list.push_back(flag);
+    }
+    return flag_list;
+  } else {
+    return Error() << flag_list_cxx.error_message;
+  }
+}
+
 Result<std::vector<FlagValueAndInfoSummary>> list_flags_with_info(
     const std::string& package_map,
     const std::string& flag_map,
diff --git a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
index 5044a4d..9f3cdb0 100644
--- a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
+++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
@@ -6,6 +6,23 @@
 
 namespace aconfig_storage {
 
+/// Flag value summary for a flag
+struct FlagValueSummary {
+  std::string package_name;
+  std::string flag_name;
+  std::string flag_value;
+  std::string value_type;
+};
+
+/// List all flag values
+/// \input package_map: package map file
+/// \input flag_map: flag map file
+/// \input flag_val: flag value file
+android::base::Result<std::vector<FlagValueSummary>> list_flags(
+    const std::string& package_map,
+    const std::string& flag_map,
+    const std::string& flag_val);
+
 /// Flag value and info summary for a flag
 struct FlagValueAndInfoSummary {
   std::string package_name;
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 80602bb..26e9c1a 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -382,6 +382,14 @@
 // Exported rust data structure and methods, c++ code will be generated
 #[cxx::bridge]
 mod ffi {
+    /// flag value summary cxx return
+    pub struct FlagValueSummaryCXX {
+        pub package_name: String,
+        pub flag_name: String,
+        pub flag_value: String,
+        pub value_type: String,
+    }
+
     /// flag value and info summary cxx return
     pub struct FlagValueAndInfoSummaryCXX {
         pub package_name: String,
@@ -394,6 +402,13 @@
     }
 
     /// list flag result cxx return
+    pub struct ListFlagValueResultCXX {
+        pub query_success: bool,
+        pub error_message: String,
+        pub flags: Vec<FlagValueSummaryCXX>,
+    }
+
+    /// list flag with info result cxx return
     pub struct ListFlagValueAndInfoResultCXX {
         pub query_success: bool,
         pub error_message: String,
@@ -402,6 +417,12 @@
 
     // Rust export to c++
     extern "Rust" {
+        pub fn list_flags_cxx(
+            package_map: &str,
+            flag_map: &str,
+            flag_val: &str,
+        ) -> ListFlagValueResultCXX;
+
         pub fn list_flags_with_info_cxx(
             package_map: &str,
             flag_map: &str,
@@ -411,6 +432,18 @@
     }
 }
 
+/// implement flag value summary cxx return type
+impl ffi::FlagValueSummaryCXX {
+    pub(crate) fn new(summary: FlagValueSummary) -> Self {
+        Self {
+            package_name: summary.package_name,
+            flag_name: summary.flag_name,
+            flag_value: summary.flag_value,
+            value_type: format!("{:?}", summary.value_type),
+        }
+    }
+}
+
 /// implement flag value and info summary cxx return type
 impl ffi::FlagValueAndInfoSummaryCXX {
     pub(crate) fn new(summary: FlagValueAndInfoSummary) -> Self {
@@ -426,6 +459,26 @@
     }
 }
 
+/// implement list flag cxx interlop
+pub fn list_flags_cxx(
+    package_map: &str,
+    flag_map: &str,
+    flag_val: &str,
+) -> ffi::ListFlagValueResultCXX {
+    match list_flags(package_map, flag_map, flag_val) {
+        Ok(summary) => ffi::ListFlagValueResultCXX {
+            query_success: true,
+            error_message: String::new(),
+            flags: summary.into_iter().map(ffi::FlagValueSummaryCXX::new).collect(),
+        },
+        Err(errmsg) => ffi::ListFlagValueResultCXX {
+            query_success: false,
+            error_message: format!("{:?}", errmsg),
+            flags: Vec::new(),
+        },
+    }
+}
+
 /// implement list flag with info cxx interlop
 pub fn list_flags_with_info_cxx(
     package_map: &str,
diff --git a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
index eccbca5..ebd1dd8 100644
--- a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
+++ b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
@@ -24,15 +24,25 @@
 using namespace android::base;
 using namespace aconfig_storage;
 
+void verify_value(const FlagValueSummary& flag,
+                  const std::string& package_name,
+                  const std::string& flag_name,
+                  const std::string& flag_val,
+                  const std::string& value_type) {
+  ASSERT_EQ(flag.package_name, package_name);
+  ASSERT_EQ(flag.flag_name, flag_name);
+  ASSERT_EQ(flag.flag_value, flag_val);
+  ASSERT_EQ(flag.value_type, value_type);
+}
 
-void verify_flag(const FlagValueAndInfoSummary& flag,
-                 const std::string& package_name,
-                 const std::string& flag_name,
-                 const std::string& flag_val,
-                 const std::string& value_type,
-                 bool is_readwrite,
-                 bool has_server_override,
-                 bool has_local_override) {
+void verify_value_info(const FlagValueAndInfoSummary& flag,
+                       const std::string& package_name,
+                       const std::string& flag_name,
+                       const std::string& flag_val,
+                       const std::string& value_type,
+                       bool is_readwrite,
+                       bool has_server_override,
+                       bool has_local_override) {
   ASSERT_EQ(flag.package_name, package_name);
   ASSERT_EQ(flag.flag_name, flag_name);
   ASSERT_EQ(flag.flag_value, flag_val);
@@ -42,6 +52,35 @@
   ASSERT_EQ(flag.has_local_override, has_local_override);
 }
 
+TEST(AconfigStorageFileTest, test_list_flag) {
+  auto const test_dir = GetExecutableDirectory();
+  auto const package_map = test_dir + "/package.map";
+  auto const flag_map = test_dir + "/flag.map";
+  auto const flag_val = test_dir + "/flag.val";
+  auto flag_list_result = aconfig_storage::list_flags(
+      package_map, flag_map, flag_val);
+  ASSERT_TRUE(flag_list_result.ok());
+
+  auto const& flag_list = *flag_list_result;
+  ASSERT_EQ(flag_list.size(), 8);
+  verify_value(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
+               "false", "ReadWriteBoolean");
+  verify_value(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
+               "true", "ReadOnlyBoolean");
+  verify_value(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
+               "true", "ReadWriteBoolean");
+  verify_value(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
+               "false", "ReadWriteBoolean");
+  verify_value(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
+               "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
+               "true", "ReadOnlyBoolean");
+  verify_value(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
+               "true", "FixedReadOnlyBoolean");
+  verify_value(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
+               "true", "ReadWriteBoolean");
+}
+
 TEST(AconfigStorageFileTest, test_list_flag_with_info) {
   auto const test_dir = GetExecutableDirectory();
   auto const package_map = test_dir + "/package.map";
@@ -54,20 +93,20 @@
 
   auto const& flag_list = *flag_list_result;
   ASSERT_EQ(flag_list.size(), 8);
-  verify_flag(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
-              "false", "ReadWriteBoolean", true, false, false);
-  verify_flag(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
-              "true", "ReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
-              "true", "ReadWriteBoolean", true, false, false);
-  verify_flag(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
-              "false", "ReadWriteBoolean", true, false, false);
-  verify_flag(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
-              "true", "FixedReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
-              "true", "ReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
-              "true", "FixedReadOnlyBoolean", false, false, false);
-  verify_flag(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
-              "true", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
+                    "false", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
+                    "true", "ReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
+                    "true", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
+                    "false", "ReadWriteBoolean", true, false, false);
+  verify_value_info(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
+                    "true", "FixedReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
+                    "true", "ReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
+                    "true", "FixedReadOnlyBoolean", false, false, false);
+  verify_value_info(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
+                    "true", "ReadWriteBoolean", true, false, false);
 }