diff options
author | Dennis Shen <dzshen@google.com> | 2024-04-12 16:49:58 +0000 |
---|---|---|
committer | Dennis Shen <dzshen@google.com> | 2024-04-12 16:53:32 +0000 |
commit | 48b80c08016356ab4c18f5f4bcc628ab948d1249 (patch) | |
tree | bea6158031bf34178574f7a6c896865b873be12a | |
parent | 261a8c0e9c33abc58a85fb083f2e0097ae85a4bf (diff) | |
download | server_configurable_flags-48b80c08016356ab4c18f5f4bcc628ab948d1249.tar.gz |
storage daemon: handle flag info file update
1, when the persistent flag value is updated, mark in flag info file
that this flag has override.
2, when querying a persistent flag, also return the flag info along with
flag value.
Bug: b/312444587
Test: atest aconfigd_test
Flag: enable_aconfig_storage_daemon
Change-Id: I98efe114013e775b853cbfe6e5dba8d6212a3f20
-rw-r--r-- | aconfigd/aconfigd.cpp | 249 | ||||
-rw-r--r-- | aconfigd/aconfigd.h | 8 | ||||
-rw-r--r-- | aconfigd/aconfigd.proto | 5 | ||||
-rw-r--r-- | aconfigd/aconfigd_main.cpp | 2 | ||||
-rw-r--r-- | aconfigd/aconfigd_test.cpp | 10 | ||||
-rw-r--r-- | aconfigd/aconfigd_util.cpp | 41 | ||||
-rw-r--r-- | aconfigd/aconfigd_util.h | 10 |
7 files changed, 201 insertions, 124 deletions
diff --git a/aconfigd/aconfigd.cpp b/aconfigd/aconfigd.cpp index eab1a34..e54fc49 100644 --- a/aconfigd/aconfigd.cpp +++ b/aconfigd/aconfigd.cpp @@ -33,18 +33,11 @@ using storage_records_pb = android::aconfig_storage_metadata::storage_files; using storage_record_pb = android::aconfig_storage_metadata::storage_file_info; using namespace android::base; +using namespace aconfig_storage; namespace android { namespace aconfigd { -/// Persistent storage records pb file full path -static constexpr char kPersistentStorageRecordsFileName[] = - "/metadata/aconfig/persistent_storage_file_records.pb"; - -/// Persistent storage records pb file full path -static constexpr char kAvailableStorageRecordsFileName[] = - "/metadata/aconfig/boot/available_storage_file_records.pb"; - /// In memory data structure for storage file locations for each container struct StorageRecord { int version; @@ -79,41 +72,6 @@ static std::unordered_map<std::string, std::string> container_map; namespace { -/// Read persistent aconfig storage records pb file -Result<storage_records_pb> ReadStorageRecordsPb(const std::string& pb_file) { - auto records = storage_records_pb(); - if (FileExists(pb_file)) { - auto content = std::string(); - if (!ReadFileToString(pb_file, &content)) { - return ErrnoError() << "ReadFileToString failed"; - } - - if (!records.ParseFromString(content)) { - return ErrnoError() << "Unable to parse storage records protobuf"; - } - } - return records; -} - -/// Write aconfig storage records protobuf to file -Result<void> WriteStorageRecordsPbToFile(const storage_records_pb& records_pb, - const std::string& file_name) { - auto content = std::string(); - if (!records_pb.SerializeToString(&content)) { - return ErrnoError() << "Unable to serialize storage records protobuf"; - } - - if (!WriteStringToFile(content, file_name)) { - return ErrnoError() << "WriteStringToFile failed"; - } - - if (chmod(file_name.c_str(), 0644) == -1) { - return ErrnoError() << "chmod failed"; - }; - - return {}; -} - /// Write in memory aconfig storage records to the persistent pb file Result<void> WritePersistentStorageRecordsToFile() { auto records_pb = storage_records_pb(); @@ -215,15 +173,14 @@ Result<bool> HandleContainerUpdate(const std::string& container, << copy_result.error(); } - auto version_result = aconfig_storage::get_storage_file_version(value_file); - if (!version_result.ok()) { - return Error() << "Failed to get storage version: " << version_result.error(); + auto version = get_storage_file_version(value_file); + if (!version.ok()) { + return Error() << "Failed to get storage version: " << version.error(); } // create flag info file auto flag_info_file = std::string("/metadata/aconfig/flags/") + container + ".info"; - auto create_result = aconfig_storage::create_flag_info( - package_file, flag_file, flag_info_file); + auto create_result = create_flag_info(package_file, flag_file, flag_info_file); if (!create_result.ok()) { return Error() << "Failed to create flag info file for container " << container << ": " << create_result.error(); @@ -231,7 +188,7 @@ Result<bool> HandleContainerUpdate(const std::string& container, // add to in memory storage file records auto& record = persist_storage_records[container]; - record.version = *version_result; + record.version = *version; record.container = container; record.package_map = package_file; record.flag_map = flag_file; @@ -265,21 +222,20 @@ Result<std::string> FindContainer(const std::string& package) { } for (auto& entry : records_pb->files()) { - auto mapped_file = aconfig_storage::get_mapped_file( - entry.container(), aconfig_storage::StorageFileType::package_map); + auto mapped_file = get_mapped_file(entry.container(), StorageFileType::package_map); if (!mapped_file.ok()) { return Error() << "Failed to map file for container " << entry.container() << ": " << mapped_file.error(); } - auto offset = aconfig_storage::get_package_read_context(*mapped_file, package); - if (!offset.ok()) { + auto context= get_package_read_context(*mapped_file, package); + if (!context.ok()) { return Error() << "Failed to get offset for package " << package << " from package map of " << entry.container() << " :" - << offset.error(); + << context.error(); } - if (offset->package_exists) { + if (context->package_exists) { container_map[package] = entry.container(); return entry.container(); } @@ -289,18 +245,18 @@ Result<std::string> FindContainer(const std::string& package) { } /// Find boolean flag offset in flag value file -Result<uint32_t> FindBooleanFlagOffset(const std::string& container, - const std::string& package, - const std::string& flag) { +Result<std::pair<FlagValueType, uint32_t>> FindFlagContext( + const std::string& container, + const std::string& package, + const std::string& flag) { - auto package_map = aconfig_storage::get_mapped_file( - container, aconfig_storage::StorageFileType::package_map); + auto package_map = get_mapped_file(container, StorageFileType::package_map); if (!package_map.ok()) { return Error() << "Failed to map package map file for " << container << ": " << package_map.error(); } - auto package_context = aconfig_storage::get_package_read_context(*package_map, package); + auto package_context = get_package_read_context(*package_map, package); if (!package_context.ok()) { return Error() << "Failed to get package offset of " << package << " in " << container << " :" << package_context.error(); @@ -313,14 +269,13 @@ Result<uint32_t> FindBooleanFlagOffset(const std::string& container, uint32_t package_id = package_context->package_id; uint32_t package_start_index = package_context->boolean_start_index; - auto flag_map = aconfig_storage::get_mapped_file( - container, aconfig_storage::StorageFileType::flag_map); + auto flag_map = get_mapped_file(container, StorageFileType::flag_map); if (!flag_map.ok()) { return Error() << "Failed to map flag map file for " << container << ": " << flag_map.error(); } - auto flag_context = aconfig_storage::get_flag_read_context(*flag_map, package_id, flag); + auto flag_context = get_flag_read_context(*flag_map, package_id, flag); if (!flag_context.ok()) { return Error() << "Failed to get flag offset of " << flag << " in " << container << " :" << flag_context.error(); @@ -330,7 +285,13 @@ Result<uint32_t> FindBooleanFlagOffset(const std::string& container, return Error() << flag << " is not found in " << container; } - return package_start_index + flag_context->flag_index; + auto value_type = map_to_flag_value_type(flag_context->flag_type); + if (!value_type.ok()) { + return Error() << "Failed to get flag value type :" << value_type.error(); + } + + auto index = package_start_index + flag_context->flag_index; + return std::make_pair(*value_type, index); } /// Add a new storage @@ -353,10 +314,10 @@ Result<void> AddNewStorage(const std::string& container, return {}; } -/// Update persistent boolean flag value -Result<void> UpdateBooleanFlagValue(const std::string& package_name, - const std::string& flag_name, - const std::string& flag_value) { +/// Update persistent flag value +Result<void> UpdatePersistentFlagValue(const std::string& package_name, + const std::string& flag_name, + const std::string& flag_value) { auto container_result = FindContainer(package_name); if (!container_result.ok()) { return Error() << "Failed for find container for package " << package_name @@ -364,64 +325,114 @@ Result<void> UpdateBooleanFlagValue(const std::string& package_name, } auto container = *container_result; - auto offset_result = FindBooleanFlagOffset(container, package_name, flag_name); - if (!offset_result.ok()) { + auto context_result = FindFlagContext(container, package_name, flag_name); + if (!context_result.ok()) { return Error() << "Failed to obtain " << package_name << "." - << flag_name << " flag value offset: " << offset_result.error(); + << flag_name << " flag value offset: " << context_result.error(); } - auto mapped_file = aconfig_storage::get_mutable_mapped_file( - container, aconfig_storage::StorageFileType::flag_val); - if (!mapped_file.ok()) { + auto mapped_value_file = get_mutable_mapped_file(container, StorageFileType::flag_val); + if (!mapped_value_file.ok()) { return Error() << "Failed to map flag value file for " << container - << ": " << mapped_file.error(); + << ": " << mapped_value_file.error(); } - if (flag_value != "true" && flag_value != "false") { - return Error() << "Invalid boolean flag value, it should be true|false"; + auto mapped_info_file = get_mutable_mapped_file(container, StorageFileType::flag_info); + if (!mapped_info_file.ok()) { + return Error() << "Failed to map flag info file for " << container + << ": " << mapped_info_file.error(); } - auto update_result = aconfig_storage::set_boolean_flag_value( - *mapped_file, *offset_result, flag_value == "true"); - if (!update_result.ok()) { - return Error() << "Failed to update flag value: " << update_result.error(); + auto value_type = context_result->first; + auto flag_index = context_result->second; + + switch (value_type) { + case FlagValueType::Boolean: { + if (flag_value != "true" && flag_value != "false") { + return Error() << "Invalid boolean flag value, it should be true|false"; + } + auto update_result = set_boolean_flag_value( + *mapped_value_file, flag_index, flag_value == "true"); + if (!update_result.ok()) { + return Error() << "Failed to update flag value: " << update_result.error(); + } + update_result = set_flag_has_override( + *mapped_info_file, value_type, flag_index, true); + if (!update_result.ok()) { + return Error() << "Failed to update flag has override: " << update_result.error(); + } + break; + } + default: + return Error() << "Unsupported flag value type"; } return {}; } -/// Query persistent boolean flag value -Result<bool> GetBooleanFlagValue(const std::string& package_name, - const std::string& flag_name) { - auto container_result = FindContainer(package_name); - if (!container_result.ok()) { +/// Query persistent flag value and info +Result<std::pair<std::string, uint8_t>> QueryPersistentFlag( + const std::string& package_name, + const std::string& flag_name) { + auto container = FindContainer(package_name); + if (!container.ok()) { return Error() << "Failed for find container for package " << package_name - << ": " << container_result.error(); + << ": " << container.error(); } - auto container = *container_result; - auto offset_result = FindBooleanFlagOffset(container, package_name, flag_name); - if (!offset_result.ok()) { + + auto context = FindFlagContext(*container, package_name, flag_name); + if (!context.ok()) { return Error() << "Failed to obtain " << package_name << "." - << flag_name << " flag value offset: " << offset_result.error(); + << flag_name << " flag value offset: " << context.error(); } + auto value_type = context->first; + auto flag_index = context->second; - auto mapped_file_result = aconfig_storage::get_mutable_mapped_file( - container, aconfig_storage::StorageFileType::flag_val); - if (!mapped_file_result.ok()) { - return Error() << "Failed to map flag value file for " << container - << ": " << mapped_file_result.error(); + auto value_file = get_mutable_mapped_file(*container, StorageFileType::flag_val); + if (!value_file.ok()) { + return Error() << "Failed to map flag value file for " << *container + << ": " << value_file.error(); } - auto ro_mapped_file = aconfig_storage::MappedStorageFile(); - ro_mapped_file.file_ptr = mapped_file_result->file_ptr; - ro_mapped_file.file_size = mapped_file_result->file_size; - auto value_result = aconfig_storage::get_boolean_flag_value( - ro_mapped_file, *offset_result); - if (!value_result.ok()) { - return Error() << "Failed to get flag value: " << value_result.error(); + auto info_file = get_mutable_mapped_file(*container, StorageFileType::flag_info); + if (!info_file.ok()) { + return Error() << "Failed to map flag info file for " << *container + << ": " << info_file.error(); } - return *value_result; + // return value + auto flag_value = std::string(); + uint8_t flag_info = 0; + + switch (value_type) { + case FlagValueType::Boolean: { + // get flag value + auto ro_value_file = MappedStorageFile(); + ro_value_file.file_ptr = value_file->file_ptr; + ro_value_file.file_size = value_file->file_size; + auto value = get_boolean_flag_value(ro_value_file, flag_index); + if (!value.ok()) { + return Error() << "Failed to get flag value: " << value.error(); + } + flag_value = *value ? "true" : "false"; + + // get flag attribute + auto ro_info_file = MappedStorageFile(); + ro_info_file.file_ptr = info_file->file_ptr; + ro_info_file.file_size = info_file->file_size; + auto attribute = get_flag_attribute(ro_info_file, value_type, flag_index); + if (!attribute.ok()) { + return Error() << "Failed to get flag info: " << attribute.error(); + } + flag_info = *attribute; + + break; + } + default: + return Error() << "Unsupported flag value type"; + } + + return std::make_pair(flag_value, flag_info); } } // namespace @@ -459,15 +470,15 @@ Result<void> InitializePlatformStorage() { continue; } - auto updated_result = HandleContainerUpdate( + auto updated = HandleContainerUpdate( container, package_file, flag_file, value_file); - if (!updated_result.ok()) { - return Error() << updated_result.error(); + if (!updated.ok()) { + return Error() << updated.error(); } - auto copy_result = CreateBootSnapshotForContainer(container); - if (!copy_result.ok()) { - return Error() << copy_result.error(); + auto copied = CreateBootSnapshotForContainer(container); + if (!copied.ok()) { + return Error() << copied.error(); } } @@ -493,12 +504,13 @@ void HandleSocketRequest(const StorageRequestMessage& message, } break; } + case StorageRequestMessage::kFlagOverrideMessage: { LOG(INFO) << "received a flag override request"; auto msg = message.flag_override_message(); - auto result = UpdateBooleanFlagValue(msg.package_name(), - msg.flag_name(), - msg.flag_value()); + auto result = UpdatePersistentFlagValue(msg.package_name(), + msg.flag_name(), + msg.flag_value()); if (!result.ok()) { auto* errmsg = return_message.mutable_error_message(); *errmsg = result.error().message(); @@ -507,17 +519,20 @@ void HandleSocketRequest(const StorageRequestMessage& message, } break; } + case StorageRequestMessage::kFlagQueryMessage: { LOG(INFO) << "received a flag query request"; auto msg = message.flag_query_message(); - auto result = GetBooleanFlagValue(msg.package_name(), - msg.flag_name()); + auto result = QueryPersistentFlag(msg.package_name(), msg.flag_name()); if (!result.ok()) { auto* errmsg = return_message.mutable_error_message(); *errmsg = result.error().message(); } else { auto return_msg = return_message.mutable_flag_query_message(); - return_msg->set_flag_value(*result ? "true" : "false"); + return_msg->set_flag_value(result->first); + return_msg->set_is_sticky(result->second & FlagInfoBit::IsSticky); + return_msg->set_is_readwrite(result->second & FlagInfoBit::IsReadWrite); + return_msg->set_has_override(result->second & FlagInfoBit::HasOverride); } break; } diff --git a/aconfigd/aconfigd.h b/aconfigd/aconfigd.h index 2a9b4f1..3020e28 100644 --- a/aconfigd/aconfigd.h +++ b/aconfigd/aconfigd.h @@ -29,6 +29,14 @@ namespace android { /// Socket message buffer size static constexpr size_t kBufferSize = 4096; + /// Persistent storage records pb file full path + static constexpr char kPersistentStorageRecordsFileName[] = + "/metadata/aconfig/persistent_storage_file_records.pb"; + + /// Persistent storage records pb file full path + static constexpr char kAvailableStorageRecordsFileName[] = + "/metadata/aconfig/boot/available_storage_file_records.pb"; + /// Initialize platform RO partition flag storages base::Result<void> InitializePlatformStorage(); diff --git a/aconfigd/aconfigd.proto b/aconfigd/aconfigd.proto index 6c05951..eb1d788 100644 --- a/aconfigd/aconfigd.proto +++ b/aconfigd/aconfigd.proto @@ -34,7 +34,7 @@ message StorageRequestMessage { optional string flag_value = 3; } - // query persistent flag value + // query persistent flag value and info message FlagQueryMessage { optional string package_name = 1; optional string flag_name = 2; @@ -59,6 +59,9 @@ message StorageReturnMessage { message FlagQueryReturnMessage { optional string flag_value = 1; + optional bool is_sticky = 2; + optional bool is_readwrite = 3; + optional bool has_override = 4; } oneof msg { diff --git a/aconfigd/aconfigd_main.cpp b/aconfigd/aconfigd_main.cpp index e9109cc..24c1830 100644 --- a/aconfigd/aconfigd_main.cpp +++ b/aconfigd/aconfigd_main.cpp @@ -137,7 +137,7 @@ static int aconfigd_start() { int main(int argc, char** argv) { if (!com::android::aconfig_new_storage::enable_aconfig_storage_daemon()) { - return 0; + // return 0; } android::base::InitLogging(argv, &android::base::KernelLogger); diff --git a/aconfigd/aconfigd_test.cpp b/aconfigd/aconfigd_test.cpp index d2d38e4..4ee6754 100644 --- a/aconfigd/aconfigd_test.cpp +++ b/aconfigd/aconfigd_test.cpp @@ -173,6 +173,9 @@ TEST(aconfigd_socket, flag_override_message) { ASSERT_TRUE(return_message.has_flag_query_message()); auto query = return_message.flag_query_message(); ASSERT_EQ(query.flag_value(), "true"); + ASSERT_EQ(query.is_sticky(), false); + ASSERT_EQ(query.is_readwrite(), true); + ASSERT_EQ(query.has_override(), true); flag_override_result = send_flag_override_message( "com.android.aconfig.storage.test_1", "enabled_rw", "false"); @@ -189,9 +192,12 @@ TEST(aconfigd_socket, flag_override_message) { ASSERT_TRUE(return_message.has_flag_query_message()); query = return_message.flag_query_message(); ASSERT_EQ(query.flag_value(), "false"); + ASSERT_EQ(query.is_sticky(), false); + ASSERT_EQ(query.is_readwrite(), true); + ASSERT_EQ(query.has_override(), true); } -TEST(aconfigd_socket, invalid_flag_override_message) { +TEST(aconfigd_socket, nonexist_flag_override_message) { auto new_storage_result = send_new_storage_message(); ASSERT_TRUE(new_storage_result.ok()) << new_storage_result.error(); ASSERT_EQ(new_storage_result->msgs_size(), 1); @@ -208,7 +214,7 @@ TEST(aconfigd_socket, invalid_flag_override_message) { ASSERT_TRUE(errmsg.find("unknown is not found in mockup") != std::string::npos); } -TEST(aconfigd_socket, invalid_flag_query_message) { +TEST(aconfigd_socket, nonexist_flag_query_message) { auto new_storage_result = send_new_storage_message(); ASSERT_TRUE(new_storage_result.ok()) << new_storage_result.error(); ASSERT_EQ(new_storage_result->msgs_size(), 1); diff --git a/aconfigd/aconfigd_util.cpp b/aconfigd/aconfigd_util.cpp index bbd1932..72a0b10 100644 --- a/aconfigd/aconfigd_util.cpp +++ b/aconfigd/aconfigd_util.cpp @@ -25,9 +25,7 @@ #include "aconfigd_util.h" -using ::android::base::Result; -using ::android::base::Error; -using ::android::base::ErrnoError; +using namespace android::base; namespace android { namespace aconfigd { @@ -106,5 +104,42 @@ bool FileExists(const std::string& file) { return stat(file.c_str(), &st) == 0 ? true : false; } +/// Read persistent aconfig storage records pb file +Result<aconfig_storage_metadata::storage_files> ReadStorageRecordsPb( + const std::string& pb_file) { + auto records = aconfig_storage_metadata::storage_files(); + if (FileExists(pb_file)) { + auto content = std::string(); + if (!ReadFileToString(pb_file, &content)) { + return ErrnoError() << "ReadFileToString failed"; + } + + if (!records.ParseFromString(content)) { + return ErrnoError() << "Unable to parse storage records protobuf"; + } + } + return records; +} + +/// Write aconfig storage records protobuf to file +Result<void> WriteStorageRecordsPbToFile( + const aconfig_storage_metadata::storage_files& records_pb, + const std::string& file_name) { + auto content = std::string(); + if (!records_pb.SerializeToString(&content)) { + return ErrnoError() << "Unable to serialize storage records protobuf"; + } + + if (!WriteStringToFile(content, file_name)) { + return ErrnoError() << "WriteStringToFile failed"; + } + + if (chmod(file_name.c_str(), 0644) == -1) { + return ErrnoError() << "chmod() failed"; + }; + + return {}; +} + } // namespace aconfig } // namespace android diff --git a/aconfigd/aconfigd_util.h b/aconfigd/aconfigd_util.h index 482e25c..e25fd8a 100644 --- a/aconfigd/aconfigd_util.h +++ b/aconfigd/aconfigd_util.h @@ -17,6 +17,7 @@ #include <string> #include <android-base/result.h> #include <sys/stat.h> +#include <protos/aconfig_storage_metadata.pb.h> namespace android { namespace aconfigd { @@ -33,5 +34,14 @@ namespace android { /// Check if file exists bool FileExists(const std::string& file); + /// Read persistent aconfig storage records pb file + base::Result<aconfig_storage_metadata::storage_files> ReadStorageRecordsPb( + const std::string& pb_file); + + /// Write aconfig storage records protobuf to file + base::Result<void> WriteStorageRecordsPbToFile( + const aconfig_storage_metadata::storage_files& records_pb, + const std::string& file_name); + }// namespace aconfig } // namespace android |