aflags: add new storage mode
Add a mode that lets the user use the new aconfig storage.
Bug: 324436145
Test: adb shell aflags list --use-new-storage
Change-Id: I97d7a229a64c6ef1aea844281298ce5449b02570
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 24b16a1..1e1e4d9 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -219,7 +219,7 @@
package_map: &str,
flag_map: &str,
flag_val: &str,
-) -> Result<Vec<(String, bool)>, AconfigStorageError> {
+) -> Result<Vec<(String, String, bool)>, AconfigStorageError> {
let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?;
let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?;
let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?;
@@ -232,10 +232,9 @@
let mut flags = Vec::new();
for node in flag_table.nodes.iter() {
let (package_name, package_offset) = package_info[node.package_id as usize];
- let full_flag_name = String::from(package_name) + "/" + &node.flag_name;
let flag_offset = package_offset + node.flag_id as u32;
let flag_value = flag_value_list.booleans[flag_offset as usize];
- flags.push((full_flag_name, flag_value));
+ flags.push((String::from(package_name), node.flag_name.clone(), flag_value));
}
flags.sort_by(|v1, v2| v1.0.cmp(&v2.0));
@@ -266,14 +265,30 @@
let flags =
list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap();
let expected = [
- (String::from("com.android.aconfig.storage.test_1/disabled_rw"), false),
- (String::from("com.android.aconfig.storage.test_1/enabled_ro"), true),
- (String::from("com.android.aconfig.storage.test_1/enabled_rw"), false),
- (String::from("com.android.aconfig.storage.test_2/disabled_ro"), false),
- (String::from("com.android.aconfig.storage.test_2/enabled_fixed_ro"), true),
- (String::from("com.android.aconfig.storage.test_2/enabled_ro"), true),
- (String::from("com.android.aconfig.storage.test_4/enabled_fixed_ro"), false),
- (String::from("com.android.aconfig.storage.test_4/enabled_ro"), true),
+ (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_ro"), true),
+ (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_rw"), false),
+ (
+ String::from("com.android.aconfig.storage.test_1"),
+ String::from("disabled_rw"),
+ false,
+ ),
+ (
+ String::from("com.android.aconfig.storage.test_2"),
+ String::from("disabled_ro"),
+ false,
+ ),
+ (
+ String::from("com.android.aconfig.storage.test_2"),
+ String::from("enabled_fixed_ro"),
+ true,
+ ),
+ (String::from("com.android.aconfig.storage.test_2"), String::from("enabled_ro"), true),
+ (String::from("com.android.aconfig.storage.test_4"), String::from("enabled_ro"), true),
+ (
+ String::from("com.android.aconfig.storage.test_4"),
+ String::from("enabled_fixed_ro"),
+ false,
+ ),
];
assert_eq!(flags, expected);
}
diff --git a/tools/aconfig/aflags/Android.bp b/tools/aconfig/aflags/Android.bp
index b36aa34..4920a6f 100644
--- a/tools/aconfig/aflags/Android.bp
+++ b/tools/aconfig/aflags/Android.bp
@@ -10,6 +10,8 @@
srcs: ["src/main.rs"],
rustlibs: [
"libaconfig_protos",
+ "libaconfig_storage_read_api",
+ "libaconfig_storage_file",
"libanyhow",
"libclap",
"libnix",
diff --git a/tools/aconfig/aflags/Cargo.toml b/tools/aconfig/aflags/Cargo.toml
index 6a08da6..cce7f9d 100644
--- a/tools/aconfig/aflags/Cargo.toml
+++ b/tools/aconfig/aflags/Cargo.toml
@@ -6,8 +6,10 @@
[dependencies]
anyhow = "1.0.69"
paste = "1.0.11"
-clap = { version = "4", features = ["derive"] }
protobuf = "3.2.0"
regex = "1.10.3"
aconfig_protos = { path = "../aconfig_protos" }
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" }
+clap = {version = "4.5.2" }
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
new file mode 100644
index 0000000..1d73688
--- /dev/null
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -0,0 +1,56 @@
+use crate::{Flag, FlagPermission, FlagSource, FlagValue, ValuePickedFrom};
+use anyhow::{anyhow, Result};
+
+use std::fs::File;
+use std::io::Read;
+
+pub struct AconfigStorageSource {}
+
+use aconfig_storage_file::protos::ProtoStorageFiles;
+
+static STORAGE_INFO_FILE_PATH: &str = "/metadata/aconfig/persistent_storage_file_records.pb";
+
+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 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 container =
+ file_info.container.ok_or(anyhow!("storage file is missing container"))?;
+
+ for (package, name, val) in
+ aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)?
+ {
+ result.push(Flag {
+ name: name.to_string(),
+ package: package.to_string(),
+ value: FlagValue::try_from(val.to_string().as_str())?,
+ container: container.to_string(),
+
+ // TODO(b/324436145): delete namespace field once DeviceConfig isn't in CLI.
+ namespace: "-".to_string(),
+
+ // TODO(b/324436145): Populate with real values once API is available.
+ staged_value: None,
+ permission: FlagPermission::ReadOnly,
+ value_picked_from: ValuePickedFrom::Default,
+ });
+ }
+ }
+
+ Ok(result)
+ }
+
+ fn override_flag(_namespace: &str, _qualified_name: &str, _value: &str) -> Result<()> {
+ todo!()
+ }
+}
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
index 808ffa0..1c453c5 100644
--- a/tools/aconfig/aflags/src/main.rs
+++ b/tools/aconfig/aflags/src/main.rs
@@ -22,6 +22,9 @@
mod device_config_source;
use device_config_source::DeviceConfigSource;
+mod aconfig_storage_source;
+use aconfig_storage_source::AconfigStorageSource;
+
#[derive(Clone, PartialEq, Debug)]
enum FlagPermission {
ReadOnly,
@@ -109,6 +112,11 @@
fn override_flag(namespace: &str, qualified_name: &str, value: &str) -> Result<()>;
}
+enum FlagSourceType {
+ DeviceConfig,
+ AconfigStorage,
+}
+
const ABOUT_TEXT: &str = "Tool for reading and writing flags.
Rows in the table from the `list` command follow this format:
@@ -139,7 +147,11 @@
#[derive(Parser, Debug)]
enum Command {
/// List all aconfig flags on this device.
- List,
+ List {
+ /// Read from the new flag storage.
+ #[clap(long)]
+ use_new_storage: bool,
+ },
/// Enable an aconfig flag on this device, on the next boot.
Enable {
@@ -201,8 +213,11 @@
Ok(())
}
-fn list() -> Result<String> {
- let flags = DeviceConfigSource::list_flags()?;
+fn list(source_type: FlagSourceType) -> Result<String> {
+ let flags = match source_type {
+ FlagSourceType::DeviceConfig => DeviceConfigSource::list_flags()?,
+ FlagSourceType::AconfigStorage => AconfigStorageSource::list_flags()?,
+ };
let padding_info = PaddingInfo {
longest_flag_col: flags.iter().map(|f| f.qualified_name().len()).max().unwrap_or(0),
longest_val_col: flags.iter().map(|f| f.value.to_string().len()).max().unwrap_or(0),
@@ -234,7 +249,8 @@
fn main() {
let cli = Cli::parse();
let output = match cli.command {
- Command::List => list().map(Some),
+ Command::List { use_new_storage: true } => list(FlagSourceType::AconfigStorage).map(Some),
+ Command::List { use_new_storage: false } => list(FlagSourceType::DeviceConfig).map(Some),
Command::Enable { qualified_name } => set_flag(&qualified_name, "true").map(|_| None),
Command::Disable { qualified_name } => set_flag(&qualified_name, "false").map(|_| None),
};