Merge "DO NOT MERGE: manually cherry pick" into aosp-main-future

This commit is contained in:
Zhi Dou
2024-08-16 15:45:14 +00:00
committed by Android (Google) Code Review
8 changed files with 320 additions and 203 deletions

View File

@@ -45,6 +45,8 @@ where
let header = package.replace('.', "_");
let package_macro = header.to_uppercase();
let cpp_namespace = package.replace('.', "::");
ensure!(class_elements.len() > 0);
let container = class_elements[0].container.clone();
ensure!(codegen::is_valid_name_ident(&header));
let context = Context {
header: &header,
@@ -56,6 +58,7 @@ where
readwrite_count,
is_test_mode: codegen_mode == CodegenMode::Test,
class_elements,
container,
allow_instrumentation,
};
@@ -100,6 +103,7 @@ pub struct Context<'a> {
pub readwrite_count: i32,
pub is_test_mode: bool,
pub class_elements: Vec<ClassElement>,
pub container: String,
pub allow_instrumentation: bool,
}

View File

@@ -287,6 +287,11 @@ lazy_static::lazy_static! {
"com.android.aconfig.test.disabled_rw",
"false") == "true";
let use_new_storage_value = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.core_experiments_team_internal",
"com.android.providers.settings.use_new_storage_value",
"false") == "true";
if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
// This will be called multiple times. Subsequent calls after the first are noops.
logger::init(
@@ -314,13 +319,25 @@ lazy_static::lazy_static! {
match aconfig_storage_result {
Ok(storage_result) if storage_result == result => {
log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Ok(storage_result) => {
log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'disabled_rw'. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Err(err) => {
log!(Level::Error, "AconfigTestMission1: error: {err}")
log!(Level::Error, "AconfigTestMission1: error: {err}");
if use_new_storage_value {
panic!("failed to read flag value: {err}");
}
}
}
}
@@ -336,6 +353,11 @@ lazy_static::lazy_static! {
"com.android.aconfig.test.disabled_rw_exported",
"false") == "true";
let use_new_storage_value = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.core_experiments_team_internal",
"com.android.providers.settings.use_new_storage_value",
"false") == "true";
if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
// This will be called multiple times. Subsequent calls after the first are noops.
logger::init(
@@ -363,13 +385,25 @@ lazy_static::lazy_static! {
match aconfig_storage_result {
Ok(storage_result) if storage_result == result => {
log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw_exported' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Ok(storage_result) => {
log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'disabled_rw_exported'. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Err(err) => {
log!(Level::Error, "AconfigTestMission1: error: {err}")
log!(Level::Error, "AconfigTestMission1: error: {err}");
if use_new_storage_value {
panic!("failed to read flag value: {err}");
}
}
}
}
@@ -385,6 +419,11 @@ lazy_static::lazy_static! {
"com.android.aconfig.test.disabled_rw_in_other_namespace",
"false") == "true";
let use_new_storage_value = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.core_experiments_team_internal",
"com.android.providers.settings.use_new_storage_value",
"false") == "true";
if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
// This will be called multiple times. Subsequent calls after the first are noops.
logger::init(
@@ -412,13 +451,25 @@ lazy_static::lazy_static! {
match aconfig_storage_result {
Ok(storage_result) if storage_result == result => {
log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw_in_other_namespace' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Ok(storage_result) => {
log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'disabled_rw_in_other_namespace'. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Err(err) => {
log!(Level::Error, "AconfigTestMission1: error: {err}")
log!(Level::Error, "AconfigTestMission1: error: {err}");
if use_new_storage_value {
panic!("failed to read flag value: {err}");
}
}
}
}
@@ -434,6 +485,11 @@ lazy_static::lazy_static! {
"com.android.aconfig.test.enabled_rw",
"true") == "true";
let use_new_storage_value = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.core_experiments_team_internal",
"com.android.providers.settings.use_new_storage_value",
"false") == "true";
if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() {
// This will be called multiple times. Subsequent calls after the first are noops.
logger::init(
@@ -461,13 +517,25 @@ lazy_static::lazy_static! {
match aconfig_storage_result {
Ok(storage_result) if storage_result == result => {
log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_rw' contained correct value. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Ok(storage_result) => {
log!(Level::Error, "AconfigTestMission1: error: mismatch for flag 'enabled_rw'. Legacy storage was {result}, new storage was {storage_result}");
if use_new_storage_value {
return storage_result;
} else {
return result;
}
},
Err(err) => {
log!(Level::Error, "AconfigTestMission1: error: {err}")
log!(Level::Error, "AconfigTestMission1: error: {err}");
if use_new_storage_value {
panic!("failed to read flag value: {err}");
}
}
}
}
@@ -589,7 +657,6 @@ pub fn disabled_ro() -> bool {
log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'disabled_ro'. Legacy storage was {result}, new storage was {value}");
} else {
let default_value = false;
log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_ro' contained correct value. Legacy storage was {default_value}, new storage was {value}");
}
}
@@ -672,7 +739,6 @@ pub fn enabled_fixed_ro() -> bool {
log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_fixed_ro'. Legacy storage was {result}, new storage was {value}");
} else {
let default_value = true;
log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_fixed_ro' contained correct value. Legacy storage was {default_value}, new storage was {value}");
}
}
@@ -737,7 +803,6 @@ pub fn enabled_fixed_ro_exported() -> bool {
log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_fixed_ro_exported'. Legacy storage was {result}, new storage was {value}");
} else {
let default_value = true;
log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_fixed_ro_exported' contained correct value. Legacy storage was {default_value}, new storage was {value}");
}
}
@@ -802,7 +867,6 @@ pub fn enabled_ro() -> bool {
log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_ro'. Legacy storage was {result}, new storage was {value}");
} else {
let default_value = true;
log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_ro' contained correct value. Legacy storage was {default_value}, new storage was {value}");
}
}
@@ -867,7 +931,6 @@ pub fn enabled_ro_exported() -> bool {
log!(Level::Error, "AconfigTestMission1: error: flag mismatch for 'enabled_ro_exported'. Legacy storage was {result}, new storage was {value}");
} else {
let default_value = true;
log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_ro_exported' contained correct value. Legacy storage was {default_value}, new storage was {value}");
}
}

View File

@@ -1,13 +1,13 @@
#include "{header}.h"
{{ if allow_instrumentation }}
{{ if readwrite- }}
#include <sys/stat.h>
#include "aconfig_storage/aconfig_storage_read_api.hpp"
#include <android/log.h>
#define ALOGI(msg, ...) \
__android_log_print(ANDROID_LOG_INFO, "AconfigTestMission1", (msg), __VA_ARGS__)
#define LOG_TAG "aconfig_cpp_codegen"
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
{{ -endif }}
{{ endif }}
{{ if readwrite- }}
@@ -66,8 +66,68 @@ namespace {cpp_namespace} \{
class flag_provider : public flag_provider_interface \{
public:
{{ -for item in class_elements }}
{{ if allow_instrumentation- }}
{{ if readwrite- }}
flag_provider()
{{ if readwrite- }}
: cache_({readwrite_count}, -1)
, boolean_start_index_()
{{ -else- }}
: boolean_start_index_()
{{ -endif }}
, flag_value_file_(nullptr)
, read_from_new_storage_(false)
, use_new_storage_value(false) \{
struct stat buffer;
if (stat("/metadata/aconfig_test_missions/mission_1", &buffer) == 0) \{
read_from_new_storage_ = true;
} else \{
return;
}
auto package_map_file = aconfig_storage::get_mapped_file(
"{container}",
aconfig_storage::StorageFileType::package_map);
if (!package_map_file.ok()) \{
ALOGI("error: failed to get package map file: %s", package_map_file.error().c_str());
return;
}
auto context = aconfig_storage::get_package_read_context(
**package_map_file, "{package}");
if (!context.ok()) \{
ALOGI("error: failed to get package read context: %s", context.error().c_str());
return;
}
// cache package boolean flag start index
boolean_start_index_ = context->boolean_start_index;
// unmap package map file and free memory
delete *package_map_file;
auto flag_value_file = aconfig_storage::get_mapped_file(
"{container}",
aconfig_storage::StorageFileType::flag_val);
if (!flag_value_file.ok()) \{
ALOGI("error: failed to get flag value file: %s", flag_value_file.error().c_str());
return;
}
// cache flag value file
flag_value_file_ = std::unique_ptr<aconfig_storage::MappedStorageFile>(
*flag_value_file);
use_new_storage_value = server_configurable_flags::GetServerConfigurableFlag(
"aconfig_flags.core_experiments_team_internal",
"com.android.providers.settings.use_new_storage_value",
"false") == "true";
}
{{ -endif }}
{{ -endif }}
{{ -for item in class_elements }}
virtual bool {item.flag_name}() override \{
{{ -if item.readwrite }}
if (cache_[{item.readwrite_idx}] == -1) \{
@@ -76,6 +136,39 @@ namespace {cpp_namespace} \{
"{item.device_config_flag}",
"{item.default_value}") == "true";
}
{{ if allow_instrumentation- }}
if (read_from_new_storage_) \{
if (!flag_value_file_) \{
ALOGI("error: failed to get flag {item.flag_name}: flag value file is null");
return cache_[{item.readwrite_idx}];
}
auto value = aconfig_storage::get_boolean_flag_value(
*flag_value_file_,
boolean_start_index_ + {item.flag_offset});
if (!value.ok()) \{
ALOGI("error: failed to read flag value: %s", value.error().c_str());
return cache_[{item.readwrite_idx}];
}
bool expected_value = cache_[{item.readwrite_idx}];
if (*value != expected_value) \{
ALOGI("error: {item.flag_name} value mismatch, new storage value is %s, old storage value is %s",
*value ? "true" : "false", expected_value ? "true" : "false");
}
if (use_new_storage_value) \{
return *value;
} else \{
return expected_value;
}
}
{{ -endif }}
return cache_[{item.readwrite_idx}];
{{ -else }}
{{ -if item.is_fixed_read_only }}
@@ -86,12 +179,21 @@ namespace {cpp_namespace} \{
{{ -endif }}
}
{{ -endfor }}
{{ if readwrite- }}
private:
std::vector<int8_t> cache_ = std::vector<int8_t>({readwrite_count}, -1);
{{ -endif }}
};
{{ if allow_instrumentation- }}
uint32_t boolean_start_index_;
std::unique_ptr<aconfig_storage::MappedStorageFile> flag_value_file_;
bool read_from_new_storage_;
bool use_new_storage_value;
{{ -endif }}
{{ -endif }}
};
{{ -endif }}
@@ -107,62 +209,6 @@ bool {header}_{item.flag_name}() \{
{{ -if item.readwrite }}
return {cpp_namespace}::{item.flag_name}();
{{ -else }}
{{ if allow_instrumentation }}
auto result =
{{ if item.is_fixed_read_only }}
{package_macro}_{item.flag_macro}
{{ else }}
{item.default_value}
{{ endif }};
struct stat buffer;
if (stat("/metadata/aconfig_test_missions/mission_1", &buffer) != 0) \{
return result;
}
auto package_map_file = aconfig_storage::get_mapped_file(
"{item.container}",
aconfig_storage::StorageFileType::package_map);
if (!package_map_file.ok()) \{
ALOGI("error: failed to get package map file: %s", package_map_file.error().c_str());
return result;
}
auto package_read_context = aconfig_storage::get_package_read_context(
**package_map_file, "{package}");
if (!package_read_context.ok()) \{
ALOGI("error: failed to get package read context: %s", package_map_file.error().c_str());
return result;
}
delete *package_map_file;
auto flag_val_map = aconfig_storage::get_mapped_file(
"{item.container}",
aconfig_storage::StorageFileType::flag_val);
if (!flag_val_map.ok()) \{
ALOGI("error: failed to get flag val map: %s", package_map_file.error().c_str());
return result;
}
auto value = aconfig_storage::get_boolean_flag_value(
**flag_val_map,
package_read_context->boolean_start_index + {item.flag_offset});
if (!value.ok()) \{
ALOGI("error: failed to get flag val: %s", package_map_file.error().c_str());
return result;
}
delete *flag_val_map;
if (*value != result) \{
ALOGI("error: new storage value '%d' does not match current value '%d'", *value, result);
} else \{
ALOGI("success: new storage value was '%d, legacy storage was '%d'", *value, result);
}
return result;
{{ else }}
{{ -if item.is_fixed_read_only }}
return {package_macro}_{item.flag_macro};
{{ -else }}
@@ -170,7 +216,6 @@ bool {header}_{item.flag_name}() \{
{{ -endif }}
{{ -endif }}
{{ -endif }}
{{ -endif }}
}
{{ -if is_test_mode }}
@@ -185,5 +230,3 @@ void {header}_reset_flags() \{
{cpp_namespace}::reset_flags();
}
{{ -endif }}

View File

@@ -35,6 +35,11 @@ lazy_static::lazy_static! \{
"{flag.device_config_flag}",
"{flag.default_value}") == "true";
let use_new_storage_value = flags_rust::GetServerConfigurableFlag(
"aconfig_flags.core_experiments_team_internal",
"com.android.providers.settings.use_new_storage_value",
"false") == "true";
if Path::new(STORAGE_MIGRATION_MARKER_FILE).exists() \{
// This will be called multiple times. Subsequent calls after the first are noops.
logger::init(
@@ -62,13 +67,25 @@ lazy_static::lazy_static! \{
match aconfig_storage_result \{
Ok(storage_result) if storage_result == result => \{
log!(Level::Info, "AconfigTestMission1: success! flag '{flag.name}' contained correct value. Legacy storage was \{result}, new storage was \{storage_result}");
if use_new_storage_value \{
return storage_result;
} else \{
return result;
}
},
Ok(storage_result) => \{
log!(Level::Error, "AconfigTestMission1: error: mismatch for flag '{flag.name}'. Legacy storage was \{result}, new storage was \{storage_result}");
if use_new_storage_value \{
return storage_result;
} else \{
return result;
}
},
Err(err) => \{
log!(Level::Error, "AconfigTestMission1: error: \{err}")
log!(Level::Error, "AconfigTestMission1: error: \{err}");
if use_new_storage_value \{
panic!("failed to read flag value: \{err}");
}
}
}
}
@@ -168,7 +185,6 @@ pub fn {flag.name}() -> bool \{
log!(Level::Error, "AconfigTestMission1: error: flag mismatch for '{flag.name}'. Legacy storage was \{result}, new storage was \{value}");
} else \{
let default_value = {flag.default_value};
log!(Level::Info, "AconfigTestMission1: success! flag '{flag.name}' contained correct value. Legacy storage was \{default_value}, new storage was \{value}");
}
}

View File

@@ -11,6 +11,7 @@ rust_defaults {
rustlibs: [
"libaconfig_device_paths",
"libaconfig_protos",
"libaconfigd_protos",
"libaconfig_storage_read_api",
"libaconfig_storage_file",
"libanyhow",

View File

@@ -9,6 +9,7 @@ paste = "1.0.11"
protobuf = "3.2.0"
regex = "1.10.3"
aconfig_protos = { path = "../aconfig_protos" }
aconfigd_protos = { version = "0.1.0", path = "../../../../../system/server_configurable_flags/aconfigd"}
nix = { version = "0.28.0", features = ["user"] }
aconfig_storage_file = { version = "0.1.0", path = "../aconfig_storage_file" }
aconfig_storage_read_api = { version = "0.1.0", path = "../aconfig_storage_read_api" }

View File

@@ -1,136 +1,125 @@
use crate::{Flag, FlagPermission, FlagSource, FlagValue, ValuePickedFrom};
use anyhow::{anyhow, Result};
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use crate::{Flag, FlagSource};
use crate::{FlagPermission, FlagValue, ValuePickedFrom};
use aconfigd_protos::{
ProtoFlagQueryReturnMessage, ProtoListStorageMessage, ProtoListStorageMessageMsg,
ProtoStorageRequestMessage, ProtoStorageRequestMessageMsg, ProtoStorageRequestMessages,
ProtoStorageReturnMessage, ProtoStorageReturnMessageMsg, ProtoStorageReturnMessages,
};
use anyhow::anyhow;
use anyhow::Result;
use protobuf::Message;
use protobuf::SpecialFields;
use std::io::{Read, Write};
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
pub struct AconfigStorageSource {}
use aconfig_storage_file::protos::ProtoStorageFileInfo;
use aconfig_storage_file::protos::ProtoStorageFiles;
use aconfig_storage_file::FlagValueAndInfoSummary;
fn convert(msg: ProtoFlagQueryReturnMessage) -> Result<Flag> {
let (value, value_picked_from) = match (
&msg.boot_flag_value,
msg.default_flag_value,
msg.local_flag_value,
msg.has_local_override,
) {
(_, _, Some(local), Some(has_local)) if has_local => {
(FlagValue::try_from(local.as_str())?, ValuePickedFrom::Local)
}
(Some(boot), Some(default), _, _) => {
let value = FlagValue::try_from(boot.as_str())?;
if *boot == default {
(value, ValuePickedFrom::Default)
} else {
(value, ValuePickedFrom::Server)
}
}
_ => return Err(anyhow!("missing override")),
};
static STORAGE_INFO_FILE_PATH: &str = "/metadata/aconfig/storage_records.pb";
let staged_value = match (msg.boot_flag_value, msg.server_flag_value, msg.has_server_override) {
(Some(boot), Some(server), _) if boot == server => None,
(Some(boot), Some(server), Some(has_server)) if boot != server && has_server => {
Some(FlagValue::try_from(server.as_str())?)
}
_ => None,
};
fn read_default_values(file_info: ProtoStorageFileInfo) -> Result<HashMap<String, FlagValue>> {
let package_map =
file_info.package_map.ok_or(anyhow!("storage file is missing package map"))?;
let flag_map = file_info.flag_map.ok_or(anyhow!("storage file is missing flag map"))?;
let flag_val = file_info.flag_val.ok_or(anyhow!("storage file is missing flag val"))?;
let permission = match msg.is_readwrite {
Some(is_readwrite) => {
if is_readwrite {
FlagPermission::ReadWrite
} else {
FlagPermission::ReadOnly
}
}
None => return Err(anyhow!("missing permission")),
};
let mut result = HashMap::new();
for listed_flag in aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)? {
let value = FlagValue::try_from(listed_flag.flag_value.as_str())?;
result.insert(listed_flag.package_name + &listed_flag.flag_name, value);
}
Ok(result)
Ok(Flag {
name: msg.flag_name.ok_or(anyhow!("missing flag name"))?,
package: msg.package_name.ok_or(anyhow!("missing package name"))?,
value,
permission,
value_picked_from,
staged_value,
container: msg.container.ok_or(anyhow!("missing container"))?,
// TODO: remove once DeviceConfig is not in the CLI.
namespace: "-".to_string(),
})
}
fn read_next_boot_values(
listed_flags: &[FlagValueAndInfoSummary],
) -> Result<HashMap<String, FlagValue>> {
let mut result = HashMap::new();
for flag in listed_flags {
result.insert(
flag.package_name.clone() + &flag.flag_name,
FlagValue::try_from(flag.flag_value.as_str())?,
);
fn read_from_socket() -> Result<Vec<ProtoFlagQueryReturnMessage>> {
let messages = ProtoStorageRequestMessages {
msgs: vec![ProtoStorageRequestMessage {
msg: Some(ProtoStorageRequestMessageMsg::ListStorageMessage(ProtoListStorageMessage {
msg: Some(ProtoListStorageMessageMsg::All(true)),
special_fields: SpecialFields::new(),
})),
special_fields: SpecialFields::new(),
}],
special_fields: SpecialFields::new(),
};
let mut socket = UnixStream::connect("/dev/socket/aconfigd")?;
let message_buffer = messages.write_to_bytes()?;
let mut message_length_buffer: [u8; 4] = [0; 4];
let message_size = &message_buffer.len();
message_length_buffer[0] = (message_size >> 24) as u8;
message_length_buffer[1] = (message_size >> 16) as u8;
message_length_buffer[2] = (message_size >> 8) as u8;
message_length_buffer[3] = *message_size as u8;
socket.write_all(&message_length_buffer)?;
socket.write_all(&message_buffer)?;
socket.shutdown(Shutdown::Write)?;
let mut response_length_buffer: [u8; 4] = [0; 4];
socket.read_exact(&mut response_length_buffer)?;
let response_length = u32::from_be_bytes(response_length_buffer) as usize;
let mut response_buffer = vec![0; response_length];
socket.read_exact(&mut response_buffer)?;
let response: ProtoStorageReturnMessages =
protobuf::Message::parse_from_bytes(&response_buffer)?;
match response.msgs.as_slice() {
[ProtoStorageReturnMessage {
msg: Some(ProtoStorageReturnMessageMsg::ListStorageMessage(list_storage_message)),
..
}] => Ok(list_storage_message.flags.clone()),
_ => Err(anyhow!("unexpected response from aconfigd")),
}
Ok(result)
}
fn reconcile(
default_values: HashMap<String, FlagValue>,
next_boot_values: HashMap<String, FlagValue>,
flags_current_boot: &[FlagValueAndInfoSummary],
container: &str,
) -> Result<Vec<Flag>> {
let mut result = Vec::new();
for listed_flag in flags_current_boot {
let default_value = default_values
.get(&(listed_flag.package_name.clone() + &listed_flag.flag_name))
.copied();
let name = listed_flag.flag_name.clone();
let package = listed_flag.package_name.clone();
let value = FlagValue::try_from(listed_flag.flag_value.as_str())?;
let container = container.to_string();
let staged_value = next_boot_values
.get(&(listed_flag.package_name.clone() + &listed_flag.flag_name))
.filter(|&v| value != *v)
.copied();
let permission = if listed_flag.is_readwrite {
FlagPermission::ReadWrite
} else {
FlagPermission::ReadOnly
};
let value_picked_from = if listed_flag.has_local_override {
ValuePickedFrom::Local
} else if Some(value) == default_value {
ValuePickedFrom::Default
} else {
ValuePickedFrom::Server
};
result.push(Flag {
name,
package,
value,
container,
staged_value,
permission,
value_picked_from,
// TODO(b/324436145): delete namespace field once DeviceConfig isn't in CLI.
namespace: "-".to_string(),
});
}
Ok(result)
}
impl FlagSource for AconfigStorageSource {
fn list_flags() -> Result<Vec<Flag>> {
let mut result = Vec::new();
let mut file = File::open(STORAGE_INFO_FILE_PATH)?;
let mut bytes = Vec::new();
file.read_to_end(&mut bytes)?;
let storage_file_info: ProtoStorageFiles = protobuf::Message::parse_from_bytes(&bytes)?;
for file_info in storage_file_info.files {
let default_values = read_default_values(file_info.clone())?;
let container =
file_info.container.ok_or(anyhow!("storage file is missing container"))?;
let package_map = format!("/metadata/aconfig/maps/{container}.package.map");
let flag_map = format!("/metadata/aconfig/maps/{container}.flag.map");
let flag_info = format!("/metadata/aconfig/boot/{container}.info");
let flag_val_current_boot = format!("/metadata/aconfig/boot/{container}.val");
let flag_val_next_boot = format!("/metadata/aconfig/flags/{container}.val");
let flags_next_boot = aconfig_storage_file::list_flags_with_info(
&package_map,
&flag_map,
&flag_val_next_boot,
&flag_info,
)?;
let flags_current_boot = aconfig_storage_file::list_flags_with_info(
&package_map,
&flag_map,
&flag_val_current_boot,
&flag_info,
)?;
let next_boot_values = read_next_boot_values(&flags_next_boot)?;
let processed_flags =
reconcile(default_values, next_boot_values, &flags_current_boot, &container)?;
result.extend(processed_flags);
}
Ok(result)
read_from_socket()
.map(|query_messages| {
query_messages.iter().map(|message| convert(message.clone())).collect::<Vec<_>>()
})?
.into_iter()
.collect()
}
fn override_flag(_namespace: &str, _qualified_name: &str, _value: &str) -> Result<()> {

View File

@@ -289,7 +289,7 @@ fn main() -> Result<()> {
let output = match cli.command {
Command::List { use_new_storage: true, container } => {
list(FlagSourceType::AconfigStorage, container)
.map_err(|_| anyhow!("storage may not be enabled"))
.map_err(|err| anyhow!("storage may not be enabled: {err}"))
.map(Some)
}
Command::List { use_new_storage: false, container } => {