Merge "Move staging value application logic to persistent_properties and add unit tests" into main
This commit is contained in:
commit
fa21f12e3b
4 changed files with 90 additions and 32 deletions
|
|
@ -46,6 +46,13 @@ namespace {
|
||||||
|
|
||||||
constexpr const char kLegacyPersistentPropertyDir[] = "/data/property";
|
constexpr const char kLegacyPersistentPropertyDir[] = "/data/property";
|
||||||
|
|
||||||
|
void AddPersistentProperty(const std::string& name, const std::string& value,
|
||||||
|
PersistentProperties* persistent_properties) {
|
||||||
|
auto persistent_property_record = persistent_properties->add_properties();
|
||||||
|
persistent_property_record->set_name(name);
|
||||||
|
persistent_property_record->set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
Result<PersistentProperties> LoadLegacyPersistentProperties() {
|
Result<PersistentProperties> LoadLegacyPersistentProperties() {
|
||||||
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir);
|
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
|
|
@ -146,13 +153,6 @@ Result<PersistentProperties> ParsePersistentPropertyFile(const std::string& file
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void AddPersistentProperty(const std::string& name, const std::string& value,
|
|
||||||
PersistentProperties* persistent_properties) {
|
|
||||||
auto persistent_property_record = persistent_properties->add_properties();
|
|
||||||
persistent_property_record->set_name(name);
|
|
||||||
persistent_property_record->set_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<PersistentProperties> LoadPersistentPropertyFile() {
|
Result<PersistentProperties> LoadPersistentPropertyFile() {
|
||||||
auto file_contents = ReadPersistentPropertyFile();
|
auto file_contents = ReadPersistentPropertyFile();
|
||||||
if (!file_contents.ok()) return file_contents.error();
|
if (!file_contents.ok()) return file_contents.error();
|
||||||
|
|
@ -266,8 +266,57 @@ PersistentProperties LoadPersistentProperties() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return *persistent_properties;
|
// loop over to find all staged props
|
||||||
|
auto const staged_prefix = std::string_view("next_boot.");
|
||||||
|
auto staged_props = std::unordered_map<std::string, std::string>();
|
||||||
|
for (const auto& property_record : persistent_properties->properties()) {
|
||||||
|
auto const& prop_name = property_record.name();
|
||||||
|
auto const& prop_value = property_record.value();
|
||||||
|
if (StartsWith(prop_name, staged_prefix)) {
|
||||||
|
auto actual_prop_name = prop_name.substr(staged_prefix.size());
|
||||||
|
staged_props[actual_prop_name] = prop_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (staged_props.empty()) {
|
||||||
|
return *persistent_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if has staging, apply staging and perserve the original prop order
|
||||||
|
PersistentProperties updated_persistent_properties;
|
||||||
|
for (const auto& property_record : persistent_properties->properties()) {
|
||||||
|
auto const& prop_name = property_record.name();
|
||||||
|
auto const& prop_value = property_record.value();
|
||||||
|
|
||||||
|
// don't include staged props anymore
|
||||||
|
if (StartsWith(prop_name, staged_prefix)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = staged_props.find(prop_name);
|
||||||
|
if (iter != staged_props.end()) {
|
||||||
|
AddPersistentProperty(prop_name, iter->second, &updated_persistent_properties);
|
||||||
|
staged_props.erase(iter);
|
||||||
|
} else {
|
||||||
|
AddPersistentProperty(prop_name, prop_value, &updated_persistent_properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add any additional staged props
|
||||||
|
for (auto const& [prop_name, prop_value] : staged_props) {
|
||||||
|
AddPersistentProperty(prop_name, prop_value, &updated_persistent_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write current updated persist prop file
|
||||||
|
auto result = WritePersistentPropertyFile(updated_persistent_properties);
|
||||||
|
if (!result.ok()) {
|
||||||
|
LOG(ERROR) << "Could not store persistent property: " << result.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated_persistent_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace init
|
} // namespace init
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,6 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace init {
|
namespace init {
|
||||||
|
|
||||||
void AddPersistentProperty(const std::string& name, const std::string& value,
|
|
||||||
PersistentProperties* persistent_properties);
|
|
||||||
PersistentProperties LoadPersistentProperties();
|
PersistentProperties LoadPersistentProperties();
|
||||||
void WritePersistentProperty(const std::string& name, const std::string& value);
|
void WritePersistentProperty(const std::string& name, const std::string& value);
|
||||||
PersistentProperties LoadPersistentPropertiesFromMemory();
|
PersistentProperties LoadPersistentPropertiesFromMemory();
|
||||||
|
|
|
||||||
|
|
@ -178,5 +178,37 @@ TEST(persistent_properties, RejectNonPersistProperty) {
|
||||||
EXPECT_FALSE(it == read_back_properties.properties().end());
|
EXPECT_FALSE(it == read_back_properties.properties().end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(persistent_properties, StagedPersistProperty) {
|
||||||
|
TemporaryFile tf;
|
||||||
|
ASSERT_TRUE(tf.fd != -1);
|
||||||
|
persistent_property_filename = tf.path;
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> persistent_properties = {
|
||||||
|
{"persist.sys.locale", "en-US"},
|
||||||
|
{"next_boot.persist.test.numbers", "54321"},
|
||||||
|
{"persist.sys.timezone", "America/Los_Angeles"},
|
||||||
|
{"persist.test.numbers", "12345"},
|
||||||
|
{"next_boot.persist.test.extra", "abc"},
|
||||||
|
};
|
||||||
|
|
||||||
|
ASSERT_RESULT_OK(
|
||||||
|
WritePersistentPropertyFile(VectorToPersistentProperties(persistent_properties)));
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> expected_persistent_properties = {
|
||||||
|
{"persist.sys.locale", "en-US"},
|
||||||
|
{"persist.sys.timezone", "America/Los_Angeles"},
|
||||||
|
{"persist.test.numbers", "54321"},
|
||||||
|
{"persist.test.extra", "abc"},
|
||||||
|
};
|
||||||
|
|
||||||
|
// lock down that staged props are applied
|
||||||
|
auto first_read_back_properties = LoadPersistentProperties();
|
||||||
|
CheckPropertiesEqual(expected_persistent_properties, first_read_back_properties);
|
||||||
|
|
||||||
|
// lock down that other props are not overwritten
|
||||||
|
auto second_read_back_properties = LoadPersistentProperties();
|
||||||
|
CheckPropertiesEqual(expected_persistent_properties, second_read_back_properties);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace init
|
} // namespace init
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
||||||
|
|
@ -1406,33 +1406,12 @@ static void HandleInitSocket() {
|
||||||
switch (init_message.msg_case()) {
|
switch (init_message.msg_case()) {
|
||||||
case InitMessage::kLoadPersistentProperties: {
|
case InitMessage::kLoadPersistentProperties: {
|
||||||
load_override_properties();
|
load_override_properties();
|
||||||
// Read persistent properties after all default values have been loaded.
|
|
||||||
// Apply staged and persistent properties
|
|
||||||
bool has_staged_prop = false;
|
|
||||||
auto const staged_prefix = std::string_view("next_boot.");
|
|
||||||
|
|
||||||
auto persistent_properties = LoadPersistentProperties();
|
auto persistent_properties = LoadPersistentProperties();
|
||||||
for (const auto& property_record : persistent_properties.properties()) {
|
for (const auto& property_record : persistent_properties.properties()) {
|
||||||
auto const& prop_name = property_record.name();
|
auto const& prop_name = property_record.name();
|
||||||
auto const& prop_value = property_record.value();
|
auto const& prop_value = property_record.value();
|
||||||
|
InitPropertySet(prop_name, prop_value);
|
||||||
if (StartsWith(prop_name, staged_prefix)) {
|
|
||||||
has_staged_prop = true;
|
|
||||||
auto actual_prop_name = prop_name.substr(staged_prefix.size());
|
|
||||||
InitPropertySet(actual_prop_name, prop_value);
|
|
||||||
} else {
|
|
||||||
InitPropertySet(prop_name, prop_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update persist prop file if there are staged props
|
|
||||||
if (has_staged_prop) {
|
|
||||||
PersistentProperties props = LoadPersistentPropertiesFromMemory();
|
|
||||||
// write current updated persist prop file
|
|
||||||
auto result = WritePersistentPropertyFile(props);
|
|
||||||
if (!result.ok()) {
|
|
||||||
LOG(ERROR) << "Could not store persistent property: " << result.error();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply debug ramdisk special settings after persistent properties are loaded.
|
// Apply debug ramdisk special settings after persistent properties are loaded.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue