Merge "aconfig: add create_flag_info cc api" into main
diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp
index b590312..390067a 100644
--- a/tools/aconfig/aconfig_storage_file/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/Android.bp
@@ -12,6 +12,7 @@
         "libtempfile",
         "libprotobuf",
         "libclap",
+        "libcxx",
         "libaconfig_storage_protos",
     ],
 }
@@ -69,3 +70,46 @@
     ],
     host_supported: true,
 }
+
+// cxx source codegen from rust api
+genrule {
+    name: "libcxx_aconfig_storage_file_bridge_code",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) > $(out)",
+    srcs: ["src/lib.rs"],
+    out: ["aconfig_storage/lib.rs.cc"],
+}
+
+// cxx header codegen from rust api
+genrule {
+    name: "libcxx_aconfig_storage_file_bridge_header",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) --header > $(out)",
+    srcs: ["src/lib.rs"],
+    out: ["aconfig_storage/lib.rs.h"],
+}
+
+// a static cc lib based on generated code
+rust_ffi_static {
+    name: "libaconfig_storage_file_cxx_bridge",
+    crate_name: "aconfig_storage_file_cxx_bridge",
+    host_supported: true,
+    srcs: ["src/lib.rs"],
+    defaults: ["aconfig_storage_file.defaults"],
+}
+
+// flag storage file cc interface
+cc_library_static {
+    name: "libaconfig_storage_file_cc",
+    srcs: ["aconfig_storage_file.cpp"],
+    generated_headers: [
+        "cxx-bridge-header",
+        "libcxx_aconfig_storage_file_bridge_header",
+    ],
+    generated_sources: ["libcxx_aconfig_storage_file_bridge_code"],
+    whole_static_libs: ["libaconfig_storage_file_cxx_bridge"],
+    export_include_dirs: ["include"],
+    static_libs: [
+        "libbase",
+    ],
+}
diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml
index 641f481..5c51e83 100644
--- a/tools/aconfig/aconfig_storage_file/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_file/Cargo.toml
@@ -12,6 +12,7 @@
 protobuf = "3.2.0"
 tempfile = "3.9.0"
 thiserror = "1.0.56"
+cxx = "1.0"
 clap = { version = "4.1.8", features = ["derive"] }
 
 [[bin]]
diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
new file mode 100644
index 0000000..4807788
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
@@ -0,0 +1,20 @@
+#include "rust/cxx.h"
+#include "aconfig_storage/lib.rs.h"
+#include "aconfig_storage/aconfig_storage_file.hpp"
+
+namespace aconfig_storage {
+android::base::Result<void> create_flag_info(
+    std::string const& package_map,
+    std::string const& flag_map,
+    std::string const& flag_info_out) {
+  auto creation_cxx = create_flag_info_cxx(
+      rust::Str(package_map.c_str()),
+      rust::Str(flag_map.c_str()),
+      rust::Str(flag_info_out.c_str()));
+  if (creation_cxx.success) {
+    return {};
+  } else {
+    return android::base::Error() << creation_cxx.error_message;
+  }
+}
+} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs
index 1feeb60..894b71c 100644
--- a/tools/aconfig/aconfig_storage_file/build.rs
+++ b/tools/aconfig/aconfig_storage_file/build.rs
@@ -14,4 +14,7 @@
         .inputs(proto_files)
         .cargo_out_dir("aconfig_storage_protos")
         .run_from_script();
+
+    let _ = cxx_build::bridge("src/lib.rs");
+    println!("cargo:rerun-if-changed=src/lib.rs");
 }
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
new file mode 100644
index 0000000..31af8cd
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <stdint.h>
+#include <string>
+#include <android-base/result.h>
+
+namespace aconfig_storage {
+/// Create flag info file based on package and flag map
+/// \input package_map: package map file
+/// \input flag_map: flag map file
+/// \input flag_info_out: flag info file to be created
+android::base::Result<void> create_flag_info(
+    std::string const& package_map,
+    std::string const& flag_map,
+    std::string const& flag_info_out);
+} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 3b975d9..229c3d5 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -332,6 +332,43 @@
     Ok(())
 }
 
+// *************************************** //
+// CC INTERLOP
+// *************************************** //
+#[cxx::bridge]
+mod ffi {
+    pub struct FlagInfoCreationCXX {
+        pub success: bool,
+        pub error_message: String,
+    }
+
+    extern "Rust" {
+        pub fn create_flag_info_cxx(
+            package_map: &str,
+            flag_map: &str,
+            flag_info_out: &str,
+        ) -> FlagInfoCreationCXX;
+    }
+}
+
+/// Create flag info file cc interlop
+pub fn create_flag_info_cxx(
+    package_map: &str,
+    flag_map: &str,
+    flag_info_out: &str,
+) -> ffi::FlagInfoCreationCXX {
+    match create_flag_info(package_map, flag_map, flag_info_out) {
+        Ok(()) => ffi::FlagInfoCreationCXX {
+            success: true,
+            error_message: String::from(""),
+        },
+        Err(errmsg) => ffi::FlagInfoCreationCXX {
+            success: false,
+            error_message: format!("{:?}", errmsg),
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;