diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp index 390067a28b..b590312961 100644 --- a/tools/aconfig/aconfig_storage_file/Android.bp +++ b/tools/aconfig/aconfig_storage_file/Android.bp @@ -12,7 +12,6 @@ rust_defaults { "libtempfile", "libprotobuf", "libclap", - "libcxx", "libaconfig_storage_protos", ], } @@ -70,46 +69,3 @@ cc_library_static { ], 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 5c51e83f2d..641f481ed3 100644 --- a/tools/aconfig/aconfig_storage_file/Cargo.toml +++ b/tools/aconfig/aconfig_storage_file/Cargo.toml @@ -12,7 +12,6 @@ anyhow = "1.0.69" 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 deleted file mode 100644 index 4807788e22..0000000000 --- a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "rust/cxx.h" -#include "aconfig_storage/lib.rs.h" -#include "aconfig_storage/aconfig_storage_file.hpp" - -namespace aconfig_storage { -android::base::Result 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 894b71c10f..1feeb60677 100644 --- a/tools/aconfig/aconfig_storage_file/build.rs +++ b/tools/aconfig/aconfig_storage_file/build.rs @@ -14,7 +14,4 @@ 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_file.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp deleted file mode 100644 index 31af8cdec0..0000000000 --- a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include - -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 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 229c3d5f96..d14bab6edd 100644 --- a/tools/aconfig/aconfig_storage_file/src/lib.rs +++ b/tools/aconfig/aconfig_storage_file/src/lib.rs @@ -44,16 +44,14 @@ use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::fs::File; use std::hash::{Hash, Hasher}; -use std::io::{Read, Write}; +use std::io::Read; pub use crate::flag_info::{FlagInfoHeader, FlagInfoList, FlagInfoNode}; pub use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode}; pub use crate::flag_value::{FlagValueHeader, FlagValueList}; pub use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode}; -use crate::AconfigStorageError::{ - BytesParseFail, FileCreationFail, HashTableSizeLimit, InvalidStoredFlagType, -}; +use crate::AconfigStorageError::{BytesParseFail, HashTableSizeLimit, InvalidStoredFlagType}; /// Storage file version pub const FILE_VERSION: u32 = 1; @@ -279,104 +277,13 @@ pub fn list_flags( Ok(flags) } -/// Create flag info file -pub fn create_flag_info( - package_map: &str, - flag_map: &str, - flag_info_out: &str, -) -> Result<(), AconfigStorageError> { - let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?; - let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?; - - if package_table.header.container != flag_table.header.container { - return Err(FileCreationFail(anyhow!( - "container for package map {} and flag map {} does not match", - package_table.header.container, - flag_table.header.container, - ))); - } - - let mut package_offsets = vec![0; package_table.header.num_packages as usize]; - for node in package_table.nodes.iter() { - package_offsets[node.package_id as usize] = node.boolean_offset; - } - - let mut is_flag_rw = vec![false; flag_table.header.num_flags as usize]; - for node in flag_table.nodes.iter() { - let flag_offset = package_offsets[node.package_id as usize] + node.flag_id as u32; - is_flag_rw[flag_offset as usize] = node.flag_type == StoredFlagType::ReadWriteBoolean; - } - - let mut list = FlagInfoList { - header: FlagInfoHeader { - version: FILE_VERSION, - container: flag_table.header.container, - file_type: StorageFileType::FlagInfo as u8, - file_size: 0, - num_flags: flag_table.header.num_flags, - boolean_flag_offset: 0, - }, - nodes: is_flag_rw.iter().map(|&rw| FlagInfoNode::create(rw)).collect(), - }; - - list.header.boolean_flag_offset = list.header.into_bytes().len() as u32; - list.header.file_size = list.into_bytes().len() as u32; - - let mut file = File::create(flag_info_out).map_err(|errmsg| { - FileCreationFail(anyhow!("fail to create file {}: {}", flag_info_out, errmsg)) - })?; - file.write_all(&list.into_bytes()).map_err(|errmsg| { - FileCreationFail(anyhow!("fail to write to file {}: {}", flag_info_out, errmsg)) - })?; - - 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::*; use crate::test_utils::{ - create_test_flag_info_list, create_test_flag_table, create_test_flag_value_list, - create_test_package_table, write_bytes_to_temp_file, + create_test_flag_table, create_test_flag_value_list, create_test_package_table, + write_bytes_to_temp_file, }; - use tempfile::NamedTempFile; #[test] // this test point locks down the flag list api @@ -445,31 +352,4 @@ mod tests { ]; assert_eq!(flags, expected); } - - fn create_empty_temp_file() -> Result { - let file = NamedTempFile::new().map_err(|_| { - AconfigStorageError::FileCreationFail(anyhow!("Failed to create temp file")) - })?; - Ok(file) - } - - #[test] - // this test point locks down the flag info creation - fn test_create_flag_info() { - let package_table = - write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap(); - let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap(); - let flag_info = create_empty_temp_file().unwrap(); - - let package_table_path = package_table.path().display().to_string(); - let flag_table_path = flag_table.path().display().to_string(); - let flag_info_path = flag_info.path().display().to_string(); - - assert!(create_flag_info(&package_table_path, &flag_table_path, &flag_info_path).is_ok()); - - let flag_info = - FlagInfoList::from_bytes(&read_file_to_bytes(&flag_info_path).unwrap()).unwrap(); - let expected_flag_info = create_test_flag_info_list(); - assert_eq!(flag_info, expected_flag_info); - } } diff --git a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp index e5155a4f61..ea88f05e58 100644 --- a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp +++ b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp @@ -126,4 +126,18 @@ Result set_boolean_flag_value( return {}; } +Result 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_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp index 9e6332ac27..b652510a61 100644 --- a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp +++ b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp @@ -34,4 +34,13 @@ Result set_boolean_flag_value( uint32_t offset, bool value); +/// 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 +Result 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_write_api/src/lib.rs b/tools/aconfig/aconfig_storage_write_api/src/lib.rs index 5562d6a126..678bbd56f5 100644 --- a/tools/aconfig/aconfig_storage_write_api/src/lib.rs +++ b/tools/aconfig/aconfig_storage_write_api/src/lib.rs @@ -23,10 +23,15 @@ pub mod mapped_file; #[cfg(test)] mod test_utils; -use aconfig_storage_file::AconfigStorageError; +use aconfig_storage_file::{ + AconfigStorageError, FlagInfoHeader, FlagInfoList, FlagInfoNode, FlagTable, PackageTable, + StorageFileType, StoredFlagType, FILE_VERSION, +}; use anyhow::anyhow; use memmap2::MmapMut; +use std::fs::File; +use std::io::{Read, Write}; /// Storage file location pb file pub const STORAGE_LOCATION_FILE: &str = "/metadata/aconfig/persistent_storage_file_records.pb"; @@ -65,6 +70,86 @@ pub fn set_boolean_flag_value( }) } +/// Read in storage file as bytes +fn read_file_to_bytes(file_path: &str) -> Result, AconfigStorageError> { + let mut file = File::open(file_path).map_err(|errmsg| { + AconfigStorageError::FileReadFail(anyhow!("Failed to open file {}: {}", file_path, errmsg)) + })?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer).map_err(|errmsg| { + AconfigStorageError::FileReadFail(anyhow!( + "Failed to read bytes from file {}: {}", + file_path, + errmsg + )) + })?; + Ok(buffer) +} + +/// Create flag info file given package map file and flag map file +/// \input package_map: package map file +/// \input flag_map: flag map file +/// \output flag_info_out: created flag info file +pub fn create_flag_info( + package_map: &str, + flag_map: &str, + flag_info_out: &str, +) -> Result<(), AconfigStorageError> { + let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?; + let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?; + + if package_table.header.container != flag_table.header.container { + return Err(AconfigStorageError::FileCreationFail(anyhow!( + "container for package map {} and flag map {} does not match", + package_table.header.container, + flag_table.header.container, + ))); + } + + let mut package_offsets = vec![0; package_table.header.num_packages as usize]; + for node in package_table.nodes.iter() { + package_offsets[node.package_id as usize] = node.boolean_offset; + } + + let mut is_flag_rw = vec![false; flag_table.header.num_flags as usize]; + for node in flag_table.nodes.iter() { + let flag_offset = package_offsets[node.package_id as usize] + node.flag_id as u32; + is_flag_rw[flag_offset as usize] = node.flag_type == StoredFlagType::ReadWriteBoolean; + } + + let mut list = FlagInfoList { + header: FlagInfoHeader { + version: FILE_VERSION, + container: flag_table.header.container, + file_type: StorageFileType::FlagInfo as u8, + file_size: 0, + num_flags: flag_table.header.num_flags, + boolean_flag_offset: 0, + }, + nodes: is_flag_rw.iter().map(|&rw| FlagInfoNode::create(rw)).collect(), + }; + + list.header.boolean_flag_offset = list.header.into_bytes().len() as u32; + list.header.file_size = list.into_bytes().len() as u32; + + let mut file = File::create(flag_info_out).map_err(|errmsg| { + AconfigStorageError::FileCreationFail(anyhow!( + "fail to create file {}: {}", + flag_info_out, + errmsg + )) + })?; + file.write_all(&list.into_bytes()).map_err(|errmsg| { + AconfigStorageError::FileCreationFail(anyhow!( + "fail to write to file {}: {}", + flag_info_out, + errmsg + )) + })?; + + Ok(()) +} + // *************************************** // // CC INTERLOP // *************************************** // @@ -78,6 +163,12 @@ mod ffi { pub error_message: String, } + // Flag info file creation return for cc interlop + pub struct FlagInfoCreationCXX { + pub success: bool, + pub error_message: String, + } + // Rust export to c++ extern "Rust" { pub fn update_boolean_flag_value_cxx( @@ -85,6 +176,12 @@ mod ffi { offset: u32, value: bool, ) -> BooleanFlagValueUpdateCXX; + + pub fn create_flag_info_cxx( + package_map: &str, + flag_map: &str, + flag_info_out: &str, + ) -> FlagInfoCreationCXX; } } @@ -104,14 +201,33 @@ pub(crate) fn update_boolean_flag_value_cxx( } } +/// Create flag info file cc interlop +pub(crate) 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::*; use crate::test_utils::copy_to_temp_file; use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file; + use aconfig_storage_file::test_utils::{ + create_test_flag_info_list, create_test_flag_table, create_test_package_table, + write_bytes_to_temp_file, + }; use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value; use std::fs::File; use std::io::Read; + use tempfile::NamedTempFile; fn get_boolean_flag_value_at_offset(file: &str, offset: u32) -> bool { let mut f = File::open(&file).unwrap(); @@ -156,4 +272,31 @@ files {{ } } } + + fn create_empty_temp_file() -> Result { + let file = NamedTempFile::new().map_err(|_| { + AconfigStorageError::FileCreationFail(anyhow!("Failed to create temp file")) + })?; + Ok(file) + } + + #[test] + // this test point locks down the flag info creation + fn test_create_flag_info() { + let package_table = + write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap(); + let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap(); + let flag_info = create_empty_temp_file().unwrap(); + + let package_table_path = package_table.path().display().to_string(); + let flag_table_path = flag_table.path().display().to_string(); + let flag_info_path = flag_info.path().display().to_string(); + + assert!(create_flag_info(&package_table_path, &flag_table_path, &flag_info_path).is_ok()); + + let flag_info = + FlagInfoList::from_bytes(&read_file_to_bytes(&flag_info_path).unwrap()).unwrap(); + let expected_flag_info = create_test_flag_info_list(); + assert_eq!(flag_info, expected_flag_info); + } } diff --git a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp index d2a52fe09e..5b23dbc5bf 100644 --- a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp +++ b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp @@ -39,4 +39,5 @@ cc_test { "device-tests", "general-tests", ], + ldflags: ["-Wl,--allow-multiple-definition"], }