summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Shen <dzshen@google.com>2024-04-12 16:49:58 +0000
committerDennis Shen <dzshen@google.com>2024-04-12 16:53:32 +0000
commit48b80c08016356ab4c18f5f4bcc628ab948d1249 (patch)
treebea6158031bf34178574f7a6c896865b873be12a
parent261a8c0e9c33abc58a85fb083f2e0097ae85a4bf (diff)
downloadserver_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.cpp249
-rw-r--r--aconfigd/aconfigd.h8
-rw-r--r--aconfigd/aconfigd.proto5
-rw-r--r--aconfigd/aconfigd_main.cpp2
-rw-r--r--aconfigd/aconfigd_test.cpp10
-rw-r--r--aconfigd/aconfigd_util.cpp41
-rw-r--r--aconfigd/aconfigd_util.h10
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