Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58ada6f9 authored by Dennis Shen's avatar Dennis Shen
Browse files

aconfig: add flag info read c api

Bug: b/321077378
Test: atest aconfig_storage_read_api.test.cpp
Change-Id: If6c258429b8d8ccc872cac9f72cb533cf454ecbd
parent 2ac7a4c2
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ static Result<std::string> find_storage_file(
          return entry.flag_map();
        case StorageFileType::flag_val:
          return entry.flag_val();
        case StorageFileType::flag_info:
          return entry.flag_info();
        default:
          return Error() << "Invalid file type " << file_type;
      }
@@ -174,4 +176,17 @@ Result<bool> get_boolean_flag_value(
  }
}

/// Get boolean flag attribute
Result<uint8_t> get_boolean_flag_attribute(
    MappedStorageFile const& file,
    uint32_t offset) {
  auto content = rust::Slice<const uint8_t>(
      static_cast<uint8_t*>(file.file_ptr), file.file_size);
  auto info_cxx = get_boolean_flag_attribute_cxx(content, offset);
  if (info_cxx.query_success) {
    return info_cxx.flag_attribute;
  } else {
    return Error() << info_cxx.error_message;
  }
}
} // namespace aconfig_storage
+17 −2
Original line number Diff line number Diff line
@@ -10,7 +10,8 @@ namespace aconfig_storage {
enum StorageFileType {
  package_map,
  flag_map,
  flag_val
  flag_val,
  flag_info
};

/// Mapped storage file
@@ -76,10 +77,24 @@ android::base::Result<FlagOffset> get_flag_offset(

/// Get boolean flag value
/// \input file: mapped storage file
/// \input offset: the boolean flag value byte offset in the file
/// \input offset: the boolean flag value offset in the file
/// \returns the boolean flag value
android::base::Result<bool> get_boolean_flag_value(
    MappedStorageFile const& file,
    uint32_t offset);

/// Flag info enum, to be consistent with the one defined in src/lib.rs
enum FlagInfoBit {
  IsSticky = 1<<0,
  IsReadWrite = 1<<1,
  HasOverride = 1<<2,
};

/// Get boolean flag attribute
/// \input file: mapped storage file
/// \input offset: the boolean flag info offset in the file
/// \returns the boolean flag attribute
android::base::Result<uint8_t> get_boolean_flag_attribute(
    MappedStorageFile const& file,
    uint32_t offset);
} // namespace aconfig_storage
+30 −0
Original line number Diff line number Diff line
@@ -197,6 +197,13 @@ mod ffi {
        pub flag_value: bool,
    }

    // Flag info query return for cc interlop
    pub struct BooleanFlagAttributeQueryCXX {
        pub query_success: bool,
        pub error_message: String,
        pub flag_attribute: u8,
    }

    // Rust export to c++
    extern "Rust" {
        pub fn get_storage_file_version_cxx(file_path: &str) -> VersionNumberQueryCXX;
@@ -206,6 +213,8 @@ mod ffi {
        pub fn get_flag_offset_cxx(file: &[u8], package_id: u32, flag: &str) -> FlagOffsetQueryCXX;

        pub fn get_boolean_flag_value_cxx(file: &[u8], offset: u32) -> BooleanFlagValueQueryCXX;

        pub fn get_boolean_flag_attribute_cxx(file: &[u8], offset: u32) -> BooleanFlagAttributeQueryCXX;
    }
}

@@ -284,6 +293,22 @@ impl ffi::BooleanFlagValueQueryCXX {
    }
}

/// Implement the flag info interlop return type, create from actual flag info api return type
impl ffi::BooleanFlagAttributeQueryCXX {
    pub(crate) fn new(info_result: Result<u8, AconfigStorageError>) -> Self {
        match info_result {
            Ok(info) => {
                Self { query_success: true, error_message: String::from(""), flag_attribute: info }
            }
            Err(errmsg) => Self {
                query_success: false,
                error_message: format!("{:?}", errmsg),
                flag_attribute: 0u8,
            },
        }
    }
}

/// Implement the storage version number interlop return type, create from actual version number
/// api return type
impl ffi::VersionNumberQueryCXX {
@@ -318,6 +343,11 @@ pub fn get_boolean_flag_value_cxx(file: &[u8], offset: u32) -> ffi::BooleanFlagV
    ffi::BooleanFlagValueQueryCXX::new(find_boolean_flag_value(file, offset))
}

/// Get boolean flag attribute cc interlop
pub fn get_boolean_flag_attribute_cxx(file: &[u8], offset: u32) -> ffi::BooleanFlagAttributeQueryCXX {
    ffi::BooleanFlagAttributeQueryCXX::new(find_boolean_flag_attribute(file, offset))
}

/// Get storage version number cc interlop
pub fn get_storage_file_version_cxx(file_path: &str) -> ffi::VersionNumberQueryCXX {
    ffi::VersionNumberQueryCXX::new(get_storage_file_version(file_path))
+37 −2
Original line number Diff line number Diff line
@@ -47,7 +47,8 @@ class AconfigStorageTest : public ::testing::Test {

  Result<std::string> write_storage_location_pb_file(std::string const& package_map,
                                                     std::string const& flag_map,
                                                     std::string const& flag_val) {
                                                     std::string const& flag_val,
                                                     std::string const& flag_info) {
    auto temp_file = std::tmpnam(nullptr);
    auto proto = storage_files();
    auto* info = proto.add_files();
@@ -56,6 +57,7 @@ class AconfigStorageTest : public ::testing::Test {
    info->set_package_map(package_map);
    info->set_flag_map(flag_map);
    info->set_flag_val(flag_val);
    info->set_flag_info(flag_info);
    info->set_timestamp(12345);

    auto content = std::string();
@@ -71,20 +73,23 @@ class AconfigStorageTest : public ::testing::Test {
    package_map = *copy_to_temp_file(test_dir + "/package.map");
    flag_map = *copy_to_temp_file(test_dir + "/flag.map");
    flag_val = *copy_to_temp_file(test_dir + "/flag.val");
    flag_info = *copy_to_temp_file(test_dir + "/flag.info");
    storage_record_pb = *write_storage_location_pb_file(
        package_map, flag_map, flag_val);
        package_map, flag_map, flag_val, flag_info);
  }

  void TearDown() override {
    std::remove(package_map.c_str());
    std::remove(flag_map.c_str());
    std::remove(flag_val.c_str());
    std::remove(flag_info.c_str());
    std::remove(storage_record_pb.c_str());
  }

  std::string package_map;
  std::string flag_map;
  std::string flag_val;
  std::string flag_info;
  std::string storage_record_pb;
};

@@ -215,3 +220,33 @@ TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_query) {
  ASSERT_EQ(value.error().message(),
            std::string("InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"));
}

/// Test to lock down storage flag info query api
TEST_F(AconfigStorageTest, test_boolean_flag_info_query) {
  auto mapped_file = private_api::get_mapped_file_impl(
      storage_record_pb, "mockup", api::StorageFileType::flag_info);
  ASSERT_TRUE(mapped_file.ok());

  auto expected_value = std::vector<bool>{
    true, false, true, false, false, false, false, false};
  for (int offset = 0; offset < 8; ++offset) {
    auto attribute = api::get_boolean_flag_attribute(*mapped_file, offset);
    ASSERT_TRUE(attribute.ok());
    ASSERT_EQ(*attribute & static_cast<uint8_t>(api::FlagInfoBit::IsSticky), 0);
    ASSERT_EQ((*attribute & static_cast<uint8_t>(api::FlagInfoBit::IsReadWrite)) != 0,
              expected_value[offset]);
    ASSERT_EQ(*attribute & static_cast<uint8_t>(api::FlagInfoBit::HasOverride), 0);
  }
}

/// Negative test to lock down the error when querying flag info out of range
TEST_F(AconfigStorageTest, test_invalid_boolean_flag_info_query) {
  auto mapped_file = private_api::get_mapped_file_impl(
      storage_record_pb, "mockup", api::StorageFileType::flag_info);
  ASSERT_TRUE(mapped_file.ok());

  auto attribute = api::get_boolean_flag_attribute(*mapped_file, 8);
  ASSERT_FALSE(attribute.ok());
  ASSERT_EQ(attribute.error().message(),
            std::string("InvalidStorageFileOffset(Flag info offset goes beyond the end of the file.)"));
}