From eb8140f1f448ca7cc61770b0a5f69afe6f9b7000 Mon Sep 17 00:00:00 2001 From: "Priyanka Advani (xWF)" Date: Fri, 16 Aug 2024 17:18:03 +0000 Subject: [PATCH] Revert "DO NOT MERGE: manually cherry pick" Revert submission 28822444-manually_cp Reason for revert: Droidmonitor created revert due to b/360378804. Reverted changes: /q/submissionid:28822444-manually_cp Change-Id: I2ea993388efb4b22d91d19c8c3017f52e44235d3 --- tools/aconfig/aconfig/src/codegen/cpp.rs | 4 - tools/aconfig/aconfig/src/codegen/rust.rs | 89 +------ .../templates/cpp_source_file.template | 173 +++++-------- tools/aconfig/aconfig/templates/rust.template | 22 +- tools/aconfig/aflags/Android.bp | 1 - tools/aconfig/aflags/Cargo.toml | 1 - .../aflags/src/aconfig_storage_source.rs | 229 +++++++++--------- tools/aconfig/aflags/src/main.rs | 2 +- 8 files changed, 202 insertions(+), 319 deletions(-) diff --git a/tools/aconfig/aconfig/src/codegen/cpp.rs b/tools/aconfig/aconfig/src/codegen/cpp.rs index 2c569da8f6..e743b2fc59 100644 --- a/tools/aconfig/aconfig/src/codegen/cpp.rs +++ b/tools/aconfig/aconfig/src/codegen/cpp.rs @@ -45,8 +45,6 @@ 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, @@ -58,7 +56,6 @@ where readwrite_count, is_test_mode: codegen_mode == CodegenMode::Test, class_elements, - container, allow_instrumentation, }; @@ -103,7 +100,6 @@ pub struct Context<'a> { pub readwrite_count: i32, pub is_test_mode: bool, pub class_elements: Vec, - pub container: String, pub allow_instrumentation: bool, } diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs index 1292e0adb5..45488b05f2 100644 --- a/tools/aconfig/aconfig/src/codegen/rust.rs +++ b/tools/aconfig/aconfig/src/codegen/rust.rs @@ -287,11 +287,6 @@ 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( @@ -319,25 +314,13 @@ lazy_static::lazy_static! { match aconfig_storage_result { Ok(storage_result) if storage_result == result => { - if use_new_storage_value { - return storage_result; - } else { - return result; - } + log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw' contained correct value. Legacy storage was {result}, new storage was {storage_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}"); - if use_new_storage_value { - panic!("failed to read flag value: {err}"); - } + log!(Level::Error, "AconfigTestMission1: error: {err}") } } } @@ -353,11 +336,6 @@ 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( @@ -385,25 +363,13 @@ lazy_static::lazy_static! { match aconfig_storage_result { Ok(storage_result) if storage_result == result => { - if use_new_storage_value { - return storage_result; - } else { - return result; - } + log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw_exported' contained correct value. Legacy storage was {result}, new storage was {storage_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}"); - if use_new_storage_value { - panic!("failed to read flag value: {err}"); - } + log!(Level::Error, "AconfigTestMission1: error: {err}") } } } @@ -419,11 +385,6 @@ 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( @@ -451,25 +412,13 @@ lazy_static::lazy_static! { match aconfig_storage_result { Ok(storage_result) if storage_result == result => { - if use_new_storage_value { - return storage_result; - } else { - return result; - } + log!(Level::Info, "AconfigTestMission1: success! flag 'disabled_rw_in_other_namespace' contained correct value. Legacy storage was {result}, new storage was {storage_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}"); - if use_new_storage_value { - panic!("failed to read flag value: {err}"); - } + log!(Level::Error, "AconfigTestMission1: error: {err}") } } } @@ -485,11 +434,6 @@ 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( @@ -517,25 +461,13 @@ lazy_static::lazy_static! { match aconfig_storage_result { Ok(storage_result) if storage_result == result => { - if use_new_storage_value { - return storage_result; - } else { - return result; - } + log!(Level::Info, "AconfigTestMission1: success! flag 'enabled_rw' contained correct value. Legacy storage was {result}, new storage was {storage_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}"); - if use_new_storage_value { - panic!("failed to read flag value: {err}"); - } + log!(Level::Error, "AconfigTestMission1: error: {err}") } } } @@ -657,6 +589,7 @@ 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}"); } } @@ -739,6 +672,7 @@ 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}"); } } @@ -803,6 +737,7 @@ 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}"); } } @@ -867,6 +802,7 @@ 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}"); } } @@ -931,6 +867,7 @@ 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}"); } } diff --git a/tools/aconfig/aconfig/templates/cpp_source_file.template b/tools/aconfig/aconfig/templates/cpp_source_file.template index b6012e7a0d..38dda7df31 100644 --- a/tools/aconfig/aconfig/templates/cpp_source_file.template +++ b/tools/aconfig/aconfig/templates/cpp_source_file.template @@ -1,13 +1,13 @@ #include "{header}.h" {{ if allow_instrumentation }} -{{ if readwrite- }} #include #include "aconfig_storage/aconfig_storage_read_api.hpp" #include -#define LOG_TAG "aconfig_cpp_codegen" -#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -{{ -endif }} + +#define ALOGI(msg, ...) \ + __android_log_print(ANDROID_LOG_INFO, "AconfigTestMission1", (msg), __VA_ARGS__) + {{ endif }} {{ if readwrite- }} @@ -66,68 +66,8 @@ namespace {cpp_namespace} \{ class flag_provider : public flag_provider_interface \{ public: - {{ 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( - *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) \{ @@ -136,39 +76,6 @@ 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 }} @@ -179,22 +86,13 @@ namespace {cpp_namespace} \{ {{ -endif }} } {{ -endfor }} - {{ if readwrite- }} private: std::vector cache_ = std::vector({readwrite_count}, -1); - {{ if allow_instrumentation- }} - uint32_t boolean_start_index_; - - std::unique_ptr flag_value_file_; - - bool read_from_new_storage_; - bool use_new_storage_value; {{ -endif }} - {{ -endif }} - }; + {{ -endif }} std::unique_ptr provider_ = @@ -209,6 +107,62 @@ 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 }} @@ -216,6 +170,7 @@ bool {header}_{item.flag_name}() \{ {{ -endif }} {{ -endif }} {{ -endif }} + {{ -endif }} } {{ -if is_test_mode }} @@ -230,3 +185,5 @@ void {header}_reset_flags() \{ {cpp_namespace}::reset_flags(); } {{ -endif }} + + diff --git a/tools/aconfig/aconfig/templates/rust.template b/tools/aconfig/aconfig/templates/rust.template index 77a9984baa..cfd9d6aec8 100644 --- a/tools/aconfig/aconfig/templates/rust.template +++ b/tools/aconfig/aconfig/templates/rust.template @@ -35,11 +35,6 @@ 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( @@ -67,25 +62,13 @@ lazy_static::lazy_static! \{ match aconfig_storage_result \{ Ok(storage_result) if storage_result == result => \{ - if use_new_storage_value \{ - return storage_result; - } else \{ - return result; - } + log!(Level::Info, "AconfigTestMission1: success! flag '{flag.name}' contained correct value. Legacy storage was \{result}, new storage was \{storage_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}"); - if use_new_storage_value \{ - panic!("failed to read flag value: \{err}"); - } + log!(Level::Error, "AconfigTestMission1: error: \{err}") } } } @@ -185,6 +168,7 @@ 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}"); } } diff --git a/tools/aconfig/aflags/Android.bp b/tools/aconfig/aflags/Android.bp index c48585aed9..2a023792b6 100644 --- a/tools/aconfig/aflags/Android.bp +++ b/tools/aconfig/aflags/Android.bp @@ -11,7 +11,6 @@ rust_defaults { rustlibs: [ "libaconfig_device_paths", "libaconfig_protos", - "libaconfigd_protos", "libaconfig_storage_read_api", "libaconfig_storage_file", "libanyhow", diff --git a/tools/aconfig/aflags/Cargo.toml b/tools/aconfig/aflags/Cargo.toml index 7dc343668d..eeae295316 100644 --- a/tools/aconfig/aflags/Cargo.toml +++ b/tools/aconfig/aflags/Cargo.toml @@ -9,7 +9,6 @@ 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" } diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs index a2c60128b5..0dfb95637e 100644 --- a/tools/aconfig/aflags/src/aconfig_storage_source.rs +++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs @@ -1,125 +1,136 @@ -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; +use crate::{Flag, FlagPermission, FlagSource, FlagValue, ValuePickedFrom}; +use anyhow::{anyhow, Result}; + +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; pub struct AconfigStorageSource {} -fn convert(msg: ProtoFlagQueryReturnMessage) -> Result { - 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")), - }; +use aconfig_storage_file::protos::ProtoStorageFileInfo; +use aconfig_storage_file::protos::ProtoStorageFiles; +use aconfig_storage_file::FlagValueAndInfoSummary; - 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, - }; +static STORAGE_INFO_FILE_PATH: &str = "/metadata/aconfig/storage_records.pb"; - let permission = match msg.is_readwrite { - Some(is_readwrite) => { - if is_readwrite { - FlagPermission::ReadWrite - } else { - FlagPermission::ReadOnly - } - } - None => return Err(anyhow!("missing permission")), - }; +fn read_default_values(file_info: ProtoStorageFileInfo) -> Result> { + 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"))?; - 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(), - }) + 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) } -fn read_from_socket() -> Result> { - 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")), +fn read_next_boot_values( + listed_flags: &[FlagValueAndInfoSummary], +) -> Result> { + 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())?, + ); } + Ok(result) +} + +fn reconcile( + default_values: HashMap, + next_boot_values: HashMap, + flags_current_boot: &[FlagValueAndInfoSummary], + container: &str, +) -> Result> { + 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> { - read_from_socket() - .map(|query_messages| { - query_messages.iter().map(|message| convert(message.clone())).collect::>() - })? - .into_iter() - .collect() + 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) } fn override_flag(_namespace: &str, _qualified_name: &str, _value: &str) -> Result<()> { diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs index d8912a946e..0a5c989ef2 100644 --- a/tools/aconfig/aflags/src/main.rs +++ b/tools/aconfig/aflags/src/main.rs @@ -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(|err| anyhow!("storage may not be enabled: {err}")) + .map_err(|_| anyhow!("storage may not be enabled")) .map(Some) } Command::List { use_new_storage: false, container } => {