diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp index 8c1e2cb9db..ff284e65e1 100644 --- a/tools/aconfig/aconfig_storage_file/Android.bp +++ b/tools/aconfig/aconfig_storage_file/Android.bp @@ -89,3 +89,52 @@ rust_protobuf { source_stem: "aconfig_storage_protos", host_supported: true, } + +cc_library_static { + name: "libaconfig_storage_protos_cc", + proto: { + export_proto_headers: true, + type: "lite", + }, + srcs: ["protos/aconfig_storage_metadata.proto"], + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + host_supported: true, +} + +genrule { + name: "libcxx_aconfig_storage_bridge_code", + tools: ["cxxbridge"], + cmd: "$(location cxxbridge) $(in) > $(out)", + srcs: ["src/lib.rs"], + out: ["aconfig_storage/lib.rs.cc"], +} + +genrule { + name: "libcxx_aconfig_storage_bridge_header", + tools: ["cxxbridge"], + cmd: "$(location cxxbridge) $(in) --header > $(out)", + srcs: ["src/lib.rs"], + out: ["aconfig_storage/lib.rs.h"], +} + +rust_ffi_static { + name: "libaconfig_storage_cxx_bridge", + crate_name: "aconfig_storage_cxx_bridge", + host_supported: true, + defaults: ["aconfig_storage_file.defaults"], +} + +cc_library_static { + name: "libaconfig_storage_cc", + srcs: ["aconfig_storage.cpp"], + generated_headers: [ + "cxx-bridge-header", + "libcxx_aconfig_storage_bridge_header" + ], + generated_sources: ["libcxx_aconfig_storage_bridge_code"], + whole_static_libs: ["libaconfig_storage_cxx_bridge"], + export_include_dirs: ["include"], +} diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml index 296d068b0f..c4e2670b70 100644 --- a/tools/aconfig/aconfig_storage_file/Cargo.toml +++ b/tools/aconfig/aconfig_storage_file/Cargo.toml @@ -18,3 +18,4 @@ thiserror = "1.0.56" [build-dependencies] protobuf-codegen = "3.2.0" +cxx-build = "1.0" diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage.cpp new file mode 100644 index 0000000000..ac640930ac --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/aconfig_storage.cpp @@ -0,0 +1,106 @@ +#include "aconfig_storage/aconfig_storage.hpp" + +#include "rust/cxx.h" +#include "aconfig_storage/lib.rs.h" + +namespace aconfig_storage { + +/// Get package offset +PackageOffsetQuery get_package_offset( + std::string const& container, + std::string const& package) { + auto offset_cxx = get_package_offset_cxx( + rust::Str(container.c_str()), + rust::Str(package.c_str())); + auto offset = PackageOffsetQuery(); + offset.query_success = offset_cxx.query_success; + offset.error_message = std::string(offset_cxx.error_message.c_str()); + offset.package_exists = offset_cxx.package_exists; + offset.package_id = offset_cxx.package_id; + offset.boolean_offset = offset_cxx.boolean_offset; + return offset; +} + +/// Get flag offset +FlagOffsetQuery get_flag_offset( + std::string const& container, + uint32_t package_id, + std::string const& flag_name) { + auto offset_cxx = get_flag_offset_cxx( + rust::Str(container.c_str()), + package_id, + rust::Str(flag_name.c_str())); + auto offset = FlagOffsetQuery(); + offset.query_success = offset_cxx.query_success; + offset.error_message = std::string(offset_cxx.error_message.c_str()); + offset.flag_exists = offset_cxx.flag_exists; + offset.flag_offset = offset_cxx.flag_offset; + return offset; +} + +/// Get boolean flag value +BooleanFlagValueQuery get_boolean_flag_value( + std::string const& container, + uint32_t offset) { + auto value_cxx = get_boolean_flag_value_cxx( + rust::Str(container.c_str()), + offset); + auto value = BooleanFlagValueQuery(); + value.query_success = value_cxx.query_success; + value.error_message = std::string(value_cxx.error_message.c_str()); + value.flag_value = value_cxx.flag_value; + return value; +} + +namespace test_only_api { +PackageOffsetQuery get_package_offset_impl( + std::string const& pb_file, + std::string const& container, + std::string const& package) { + auto offset_cxx = get_package_offset_cxx_impl( + rust::Str(pb_file.c_str()), + rust::Str(container.c_str()), + rust::Str(package.c_str())); + auto offset = PackageOffsetQuery(); + offset.query_success = offset_cxx.query_success; + offset.error_message = std::string(offset_cxx.error_message.c_str()); + offset.package_exists = offset_cxx.package_exists; + offset.package_id = offset_cxx.package_id; + offset.boolean_offset = offset_cxx.boolean_offset; + return offset; +} + +FlagOffsetQuery get_flag_offset_impl( + std::string const& pb_file, + std::string const& container, + uint32_t package_id, + std::string const& flag_name) { + auto offset_cxx = get_flag_offset_cxx_impl( + rust::Str(pb_file.c_str()), + rust::Str(container.c_str()), + package_id, + rust::Str(flag_name.c_str())); + auto offset = FlagOffsetQuery(); + offset.query_success = offset_cxx.query_success; + offset.error_message = std::string(offset_cxx.error_message.c_str()); + offset.flag_exists = offset_cxx.flag_exists; + offset.flag_offset = offset_cxx.flag_offset; + return offset; +} + +BooleanFlagValueQuery get_boolean_flag_value_impl( + std::string const& pb_file, + std::string const& container, + uint32_t offset) { + auto value_cxx = get_boolean_flag_value_cxx_impl( + rust::Str(pb_file.c_str()), + rust::Str(container.c_str()), + offset); + auto value = BooleanFlagValueQuery(); + value.query_success = value_cxx.query_success; + value.error_message = std::string(value_cxx.error_message.c_str()); + value.flag_value = value_cxx.flag_value; + return value; +} +} // namespace test_only_api +} // namespace aconfig_storage diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs index 1feeb60677..894b71c10f 100644 --- a/tools/aconfig/aconfig_storage_file/build.rs +++ b/tools/aconfig/aconfig_storage_file/build.rs @@ -14,4 +14,7 @@ fn main() { .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.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage.hpp new file mode 100644 index 0000000000..636fb7eea5 --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +namespace aconfig_storage { + +/// Package offset query result +struct PackageOffsetQuery { + bool query_success; + std::string error_message; + bool package_exists; + uint32_t package_id; + uint32_t boolean_offset; +}; + +/// Flag offset query result +struct FlagOffsetQuery { + bool query_success; + std::string error_message; + bool flag_exists; + uint16_t flag_offset; +}; + +/// Boolean flag value query result +struct BooleanFlagValueQuery { + bool query_success; + std::string error_message; + bool flag_value; +}; + +/// Get package offset +/// \input container: the flag container name +/// \input package: the flag package name +/// \returns a PackageOffsetQuery +PackageOffsetQuery get_package_offset( + std::string const& container, + std::string const& package); + +/// Get flag offset +/// \input container: the flag container name +/// \input package_id: the flag package id obtained from package offset query +/// \input flag_name: flag name +/// \returns a FlagOffsetQuery +FlagOffsetQuery get_flag_offset( + std::string const& container, + uint32_t package_id, + std::string const& flag_name); + +/// Get boolean flag value +/// \input container: the flag container name +/// \input offset: the boolean flag value byte offset in the file +/// \returns a BooleanFlagValueQuery +BooleanFlagValueQuery get_boolean_flag_value( + std::string const& container, + uint32_t offset); + +/// DO NOT USE APIS IN THE FOLLOWING NAMESPACE, TEST ONLY +namespace test_only_api { +PackageOffsetQuery get_package_offset_impl( + std::string const& pb_file, + std::string const& container, + std::string const& package); + +FlagOffsetQuery get_flag_offset_impl( + std::string const& pb_file, + std::string const& container, + uint32_t package_id, + std::string const& flag_name); + +BooleanFlagValueQuery get_boolean_flag_value_impl( + std::string const& pb_file, + std::string const& container, + uint32_t offset); +} // namespace test_only_api +} // namespace aconfig_storage diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs index e87207aa4c..c238f24c03 100644 --- a/tools/aconfig/aconfig_storage_file/src/lib.rs +++ b/tools/aconfig/aconfig_storage_file/src/lib.rs @@ -256,6 +256,185 @@ pub fn get_boolean_flag_value(container: &str, offset: u32) -> Result PackageOffsetQueryCXX; + + pub fn get_flag_offset_cxx_impl( + pb_file: &str, + container: &str, + package_id: u32, + flag: &str, + ) -> FlagOffsetQueryCXX; + + pub fn get_boolean_flag_value_cxx_impl( + pb_file: &str, + container: &str, + offset: u32, + ) -> BooleanFlagValueQueryCXX; + + pub fn get_package_offset_cxx(container: &str, package: &str) -> PackageOffsetQueryCXX; + + pub fn get_flag_offset_cxx( + container: &str, + package_id: u32, + flag: &str, + ) -> FlagOffsetQueryCXX; + + pub fn get_boolean_flag_value_cxx(container: &str, offset: u32) + -> BooleanFlagValueQueryCXX; + } +} + +/// Get package start offset impl cc interlop +pub fn get_package_offset_cxx_impl( + pb_file: &str, + container: &str, + package: &str, +) -> ffi::PackageOffsetQueryCXX { + ffi::PackageOffsetQueryCXX::new(get_package_offset_impl(pb_file, container, package)) +} + +/// Get flag start offset impl cc interlop +pub fn get_flag_offset_cxx_impl( + pb_file: &str, + container: &str, + package_id: u32, + flag: &str, +) -> ffi::FlagOffsetQueryCXX { + ffi::FlagOffsetQueryCXX::new(get_flag_offset_impl(pb_file, container, package_id, flag)) +} + +/// Get boolean flag value impl cc interlop +pub fn get_boolean_flag_value_cxx_impl( + pb_file: &str, + container: &str, + offset: u32, +) -> ffi::BooleanFlagValueQueryCXX { + ffi::BooleanFlagValueQueryCXX::new(get_boolean_flag_value_impl(pb_file, container, offset)) +} + +/// Get package start offset cc interlop +pub fn get_package_offset_cxx(container: &str, package: &str) -> ffi::PackageOffsetQueryCXX { + ffi::PackageOffsetQueryCXX::new(get_package_offset(container, package)) +} + +/// Get flag start offset cc interlop +pub fn get_flag_offset_cxx( + container: &str, + package_id: u32, + flag: &str, +) -> ffi::FlagOffsetQueryCXX { + ffi::FlagOffsetQueryCXX::new(get_flag_offset(container, package_id, flag)) +} + +/// Get boolean flag value cc interlop +pub fn get_boolean_flag_value_cxx(container: &str, offset: u32) -> ffi::BooleanFlagValueQueryCXX { + ffi::BooleanFlagValueQueryCXX::new(get_boolean_flag_value(container, offset)) +} + +impl ffi::PackageOffsetQueryCXX { + pub(crate) fn new(offset_result: Result, AconfigStorageError>) -> Self { + match offset_result { + Ok(offset_opt) => match offset_opt { + Some(offset) => Self { + query_success: true, + error_message: String::from(""), + package_exists: true, + package_id: offset.package_id, + boolean_offset: offset.boolean_offset, + }, + None => Self { + query_success: true, + error_message: String::from(""), + package_exists: false, + package_id: 0, + boolean_offset: 0, + }, + }, + Err(errmsg) => Self { + query_success: false, + error_message: format!("{:?}", errmsg), + package_exists: false, + package_id: 0, + boolean_offset: 0, + }, + } + } +} + +impl ffi::FlagOffsetQueryCXX { + pub(crate) fn new(offset_result: Result, AconfigStorageError>) -> Self { + match offset_result { + Ok(offset_opt) => match offset_opt { + Some(offset) => Self { + query_success: true, + error_message: String::from(""), + flag_exists: true, + flag_offset: offset, + }, + None => Self { + query_success: true, + error_message: String::from(""), + flag_exists: false, + flag_offset: 0, + }, + }, + Err(errmsg) => Self { + query_success: false, + error_message: format!("{:?}", errmsg), + flag_exists: false, + flag_offset: 0, + }, + } + } +} + +impl ffi::BooleanFlagValueQueryCXX { + pub(crate) fn new(value_result: Result) -> Self { + match value_result { + Ok(value) => { + Self { query_success: true, error_message: String::from(""), flag_value: value } + } + Err(errmsg) => Self { + query_success: false, + error_message: format!("{:?}", errmsg), + flag_value: false, + }, + } + } +} + #[cfg(test)] mod tests { use super::*;