aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-05-01 19:38:23 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-05-01 19:45:26 +0000
commit0f5107439112c71e2f52e38c5dbae194e174ebdc (patch)
tree200d669b77affe37746be90baaa159d8e1e09f02
parenta2725fa4a5e56a42f86178ebf54d5113586eb690 (diff)
parent0c2ef754f384e8bc76d0a72498eec1177fab2a4c (diff)
downloadbuild-0f5107439112c71e2f52e38c5dbae194e174ebdc.tar.gz
Make change and version bump to RBT1.240501.001
Snap for 11788943 from 0c2ef754f384e8bc76d0a72498eec1177fab2a4c to build-tools-release Change-Id: I680e011dc2f20f606637a7d361d1e47b08ac41ce
-rw-r--r--core/build_id.mk2
-rw-r--r--core/product_config.rbc3
-rw-r--r--tests/run.rbc2
-rw-r--r--tests/single_value_inheritance_2/a.rbc20
-rw-r--r--tests/single_value_inheritance_2/b.rbc20
-rw-r--r--tests/single_value_inheritance_2/c.rbc21
-rw-r--r--tests/single_value_inheritance_2/d.rbc23
-rw-r--r--tests/single_value_inheritance_2/product.rbc23
-rw-r--r--tests/single_value_inheritance_2/test.rbc40
-rw-r--r--tools/aconfig/TEST_MAPPING4
-rw-r--r--tools/aconfig/aconfig/Android.bp12
-rw-r--r--tools/aconfig/aconfig_storage_file/Android.bp60
-rw-r--r--tools/aconfig/aconfig_storage_file/Cargo.toml1
-rw-r--r--tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp38
-rw-r--r--tools/aconfig/aconfig_storage_file/build.rs2
-rw-r--r--tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp31
-rw-r--r--tools/aconfig/aconfig_storage_file/src/lib.rs358
-rw-r--r--tools/aconfig/aconfig_storage_file/src/main.rs33
-rw-r--r--tools/aconfig/aconfig_storage_file/tests/Android.bp23
-rw-r--r--tools/aconfig/aconfig_storage_file/tests/flag.infobin0 -> 35 bytes
-rw-r--r--tools/aconfig/aconfig_storage_file/tests/flag.mapbin0 -> 321 bytes
-rw-r--r--tools/aconfig/aconfig_storage_file/tests/flag.valbin0 -> 35 bytes
-rw-r--r--tools/aconfig/aconfig_storage_file/tests/package.mapbin0 -> 209 bytes
-rw-r--r--tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp73
-rw-r--r--tools/aconfig/aconfig_storage_read_api/src/lib.rs2
-rw-r--r--tools/aconfig/aconfig_storage_read_api/tests/flag.infobin35 -> 35 bytes
-rw-r--r--tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp2
-rw-r--r--tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs2
-rw-r--r--tools/aconfig/aflags/src/aconfig_storage_source.rs8
29 files changed, 726 insertions, 77 deletions
diff --git a/core/build_id.mk b/core/build_id.mk
index 000249016e..3d3c408ba2 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -18,4 +18,4 @@
# (like "CRB01"). It must be a single word, and is
# capitalized by convention.
-BUILD_ID=RBT1.240430.001
+BUILD_ID=RBT1.240501.001
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 921f06805c..59e2c95903 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -351,6 +351,7 @@ def _percolate_inherited(configs, cfg_name, cfg, children_names):
if cfg.get(attr, "") == "":
cfg[attr] = value
percolated_attrs[attr] = True
+ child_cfg.pop(attr)
for attr in _options.trace_variables:
if attr in percolated_attrs:
@@ -360,7 +361,7 @@ def __move_items(to_list, from_cfg, attr):
value = from_cfg.get(attr, [])
if value:
to_list.extend(value)
- from_cfg[attr] = []
+ from_cfg.pop(attr)
def _indirect(pcm_name):
"""Returns configuration item for the inherited module."""
diff --git a/tests/run.rbc b/tests/run.rbc
index 85d6c09bc5..221b40f04d 100644
--- a/tests/run.rbc
+++ b/tests/run.rbc
@@ -26,6 +26,7 @@ load(":product.rbc", "init")
load(":board.rbc", board_init = "init")
load(":board_input_vars.rbc", board_input_vars_init = "init")
load("//build/make/tests/single_value_inheritance:test.rbc", test_single_value_inheritance = "test")
+load("//build/make/tests/single_value_inheritance_2:test.rbc", test_single_value_inheritance_2 = "test")
load("//build/make/tests/artifact_path_requirements:test.rbc", test_artifact_path_requirements = "test")
load("//build/make/tests/prefixed_sort_order:test.rbc", test_prefixed_sort_order = "test")
load("//build/make/tests/inherits_in_regular_variables:test.rbc", test_inherits_in_regular_variables = "test")
@@ -181,6 +182,7 @@ assert_eq("f", cfg["BAZ"])
assert_eq("", g.get("NEWVAR"))
test_single_value_inheritance()
+test_single_value_inheritance_2()
test_artifact_path_requirements()
test_prefixed_sort_order()
test_inherits_in_regular_variables()
diff --git a/tests/single_value_inheritance_2/a.rbc b/tests/single_value_inheritance_2/a.rbc
new file mode 100644
index 0000000000..fe186c7e84
--- /dev/null
+++ b/tests/single_value_inheritance_2/a.rbc
@@ -0,0 +1,20 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ cfg["PRODUCT_ENABLE_UFFD_GC"] = "true"
diff --git a/tests/single_value_inheritance_2/b.rbc b/tests/single_value_inheritance_2/b.rbc
new file mode 100644
index 0000000000..7d95749aa4
--- /dev/null
+++ b/tests/single_value_inheritance_2/b.rbc
@@ -0,0 +1,20 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ cfg["PRODUCT_ENABLE_UFFD_GC"] = "default"
diff --git a/tests/single_value_inheritance_2/c.rbc b/tests/single_value_inheritance_2/c.rbc
new file mode 100644
index 0000000000..e90e37d318
--- /dev/null
+++ b/tests/single_value_inheritance_2/c.rbc
@@ -0,0 +1,21 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":b.rbc", _b_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.inherit(handle, "test/b", _b_init)
diff --git a/tests/single_value_inheritance_2/d.rbc b/tests/single_value_inheritance_2/d.rbc
new file mode 100644
index 0000000000..3a88c2c17f
--- /dev/null
+++ b/tests/single_value_inheritance_2/d.rbc
@@ -0,0 +1,23 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":c.rbc", _c_init = "init")
+load(":a.rbc", _a_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.inherit(handle, "test/a", _a_init)
+ rblf.inherit(handle, "test/c", _c_init)
diff --git a/tests/single_value_inheritance_2/product.rbc b/tests/single_value_inheritance_2/product.rbc
new file mode 100644
index 0000000000..c47664db16
--- /dev/null
+++ b/tests/single_value_inheritance_2/product.rbc
@@ -0,0 +1,23 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":b.rbc", _b_init = "init")
+load(":d.rbc", _d_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.inherit(handle, "test/b", _b_init)
+ rblf.inherit(handle, "test/d", _d_init)
diff --git a/tests/single_value_inheritance_2/test.rbc b/tests/single_value_inheritance_2/test.rbc
new file mode 100644
index 0000000000..fa93aaa51e
--- /dev/null
+++ b/tests/single_value_inheritance_2/test.rbc
@@ -0,0 +1,40 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load("//build/make/tests/input_variables.rbc", input_variables_init = "init")
+load(":product.rbc", "init")
+
+
+def assert_eq(expected, actual):
+ if expected != actual:
+ fail("Expected '%s', got '%s'" % (expected, actual))
+
+# This test is testing that single value variables are "stolen" when processing the inheritance
+# graph. i.e. if you have a graph like this:
+#
+# B A
+# |\ |
+# | C |
+# \ \|
+# \ D
+# \|
+# E
+#
+# The same variable is defined in both A and B. In D, the value from A is chosen because it comes
+# alphabetically before C. But then in E, the value from D is chosen instead of the value from B,
+# because the value of B was "stolen" and sucked into C, leaving B with no value set.
+def test():
+ (globals, globals_base) = rblf.product_configuration("test/device", init, input_variables_init)
+ assert_eq("true", globals["PRODUCTS.test/device.mk.PRODUCT_ENABLE_UFFD_GC"])
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index b7ff8eff17..421e94a8a6 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -97,5 +97,9 @@
}
],
"postsubmit": [
+ {
+ // aconfig_storage file cpp integration tests
+ "name": "aconfig_storage_file.test.cpp"
+ }
]
}
diff --git a/tools/aconfig/aconfig/Android.bp b/tools/aconfig/aconfig/Android.bp
index 00a6feedc0..68521af91f 100644
--- a/tools/aconfig/aconfig/Android.bp
+++ b/tools/aconfig/aconfig/Android.bp
@@ -161,6 +161,9 @@ cc_test {
shared_libs: [
"server_configurable_flags",
],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ ],
test_suites: ["general-tests"],
}
@@ -176,6 +179,9 @@ cc_test {
shared_libs: [
"server_configurable_flags",
],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ ],
test_suites: ["general-tests"],
}
@@ -199,6 +205,9 @@ cc_test {
shared_libs: [
"server_configurable_flags",
],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ ],
test_suites: ["general-tests"],
}
*/
@@ -215,6 +224,9 @@ cc_test {
shared_libs: [
"server_configurable_flags",
],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ ],
test_suites: ["general-tests"],
}
diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp
index 08c00b0d6d..e066e31ac1 100644
--- a/tools/aconfig/aconfig_storage_file/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/Android.bp
@@ -12,6 +12,7 @@ rust_defaults {
"libtempfile",
"libprotobuf",
"libclap",
+ "libcxx",
"libaconfig_storage_protos",
],
}
@@ -77,3 +78,62 @@ cc_library {
product_available: true,
double_loadable: true,
}
+
+// cxx source codegen from rust api
+genrule {
+ name: "libcxx_aconfig_storage_file_bridge_code",
+ tools: ["cxxbridge"],
+ cmd: "$(location cxxbridge) $(in) > $(out)",
+ srcs: ["src/lib.rs"],
+ out: ["aconfig_storage/lib.rs.cc"],
+}
+
+// cxx header codegen from rust api
+genrule {
+ name: "libcxx_aconfig_storage_file_bridge_header",
+ tools: ["cxxbridge"],
+ cmd: "$(location cxxbridge) $(in) --header > $(out)",
+ srcs: ["src/lib.rs"],
+ out: ["aconfig_storage/lib.rs.h"],
+}
+
+// a static cc lib based on generated code
+rust_ffi_static {
+ name: "libaconfig_storage_file_cxx_bridge",
+ crate_name: "aconfig_storage_file_cxx_bridge",
+ host_supported: true,
+ vendor_available: true,
+ product_available: true,
+ srcs: ["src/lib.rs"],
+ defaults: ["aconfig_storage_file.defaults"],
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ min_sdk_version: "29",
+}
+
+// storage file parse api cc interface
+cc_library {
+ name: "libaconfig_storage_file_cc",
+ srcs: ["aconfig_storage_file.cpp"],
+ generated_headers: [
+ "cxx-bridge-header",
+ "libcxx_aconfig_storage_file_bridge_header",
+ ],
+ generated_sources: ["libcxx_aconfig_storage_file_bridge_code"],
+ whole_static_libs: ["libaconfig_storage_file_cxx_bridge"],
+ export_include_dirs: ["include"],
+ host_supported: true,
+ vendor_available: true,
+ product_available: true,
+ shared_libs: [
+ "libbase",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ min_sdk_version: "29",
+ double_loadable: true,
+}
diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml
index 641f481ed3..192dfad40a 100644
--- a/tools/aconfig/aconfig_storage_file/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_file/Cargo.toml
@@ -13,6 +13,7 @@ protobuf = "3.2.0"
tempfile = "3.9.0"
thiserror = "1.0.56"
clap = { version = "4.1.8", features = ["derive"] }
+cxx = "1.0"
[[bin]]
name = "aconfig-storage"
diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
new file mode 100644
index 0000000000..548078f48f
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp
@@ -0,0 +1,38 @@
+#include "rust/cxx.h"
+#include "aconfig_storage/lib.rs.h"
+
+#include "aconfig_storage/aconfig_storage_file.hpp"
+
+using namespace android::base;
+
+namespace aconfig_storage {
+
+Result<std::vector<FlagValueAndInfoSummary>> list_flags_with_info(
+ const std::string& package_map,
+ const std::string& flag_map,
+ const std::string& flag_val,
+ const std::string& flag_info) {
+ auto flag_list_cxx = list_flags_with_info_cxx(rust::Str(package_map.c_str()),
+ rust::Str(flag_map.c_str()),
+ rust::Str(flag_val.c_str()),
+ rust::Str(flag_info.c_str()));
+ if (flag_list_cxx.query_success) {
+ auto flag_list = std::vector<FlagValueAndInfoSummary>();
+ for (const auto& flag_cxx : flag_list_cxx.flags) {
+ auto flag = FlagValueAndInfoSummary();
+ flag.package_name = std::string(flag_cxx.package_name);
+ flag.flag_name = std::string(flag_cxx.flag_name);
+ flag.flag_value = std::string(flag_cxx.flag_value);
+ flag.value_type = std::string(flag_cxx.value_type);
+ flag.is_readwrite = flag_cxx.is_readwrite;
+ flag.has_server_override = flag_cxx.has_server_override;
+ flag.has_local_override = flag_cxx.has_local_override;
+ flag_list.push_back(flag);
+ }
+ return flag_list;
+ } else {
+ return Error() << flag_list_cxx.error_message;
+ }
+}
+
+} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs
index 1feeb60677..e0ade2aba0 100644
--- a/tools/aconfig/aconfig_storage_file/build.rs
+++ b/tools/aconfig/aconfig_storage_file/build.rs
@@ -14,4 +14,6 @@ fn main() {
.inputs(proto_files)
.cargo_out_dir("aconfig_storage_protos")
.run_from_script();
+
+ let _ = cxx_build::bridge("src/lib.rs");
}
diff --git a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
new file mode 100644
index 0000000000..5044a4dbfc
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <vector>
+#include <string>
+#include <android-base/result.h>
+
+namespace aconfig_storage {
+
+/// Flag value and info summary for a flag
+struct FlagValueAndInfoSummary {
+ std::string package_name;
+ std::string flag_name;
+ std::string flag_value;
+ std::string value_type;
+ bool is_readwrite;
+ bool has_server_override;
+ bool has_local_override;
+};
+
+/// List all flag values with their flag info
+/// \input package_map: package map file
+/// \input flag_map: flag map file
+/// \input flag_val: flag value file
+/// \input flag_info: flag info file
+android::base::Result<std::vector<FlagValueAndInfoSummary>> list_flags_with_info(
+ const std::string& package_map,
+ const std::string& flag_map,
+ const std::string& flag_val,
+ const std::string& flag_info);
+
+}// namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 2acfc7dbc7..80602bbfb0 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -278,12 +278,21 @@ pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageErro
Ok(buffer)
}
+/// Flag value summary
+#[derive(Debug, PartialEq)]
+pub struct FlagValueSummary {
+ pub package_name: String,
+ pub flag_name: String,
+ pub flag_value: String,
+ pub value_type: StoredFlagType,
+}
+
/// List flag values from storage files
pub fn list_flags(
package_map: &str,
flag_map: &str,
flag_val: &str,
-) -> Result<Vec<(String, String, StoredFlagType, bool)>, AconfigStorageError> {
+) -> Result<Vec<FlagValueSummary>, 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)?)?;
@@ -295,30 +304,155 @@ pub fn list_flags(
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 flag_offset = package_offset + node.flag_index as u32;
- let flag_value = flag_value_list.booleans[flag_offset as usize];
- flags.push((
- String::from(package_name),
- node.flag_name.clone(),
- node.flag_type,
- flag_value,
- ));
+ let (package_name, boolean_start_index) = package_info[node.package_id as usize];
+ let flag_index = boolean_start_index + node.flag_index as u32;
+ let flag_value = flag_value_list.booleans[flag_index as usize];
+ flags.push(FlagValueSummary {
+ package_name: String::from(package_name),
+ flag_name: node.flag_name.clone(),
+ flag_value: flag_value.to_string(),
+ value_type: node.flag_type,
+ });
}
- flags.sort_by(|v1, v2| match v1.0.cmp(&v2.0) {
- Ordering::Equal => v1.1.cmp(&v2.1),
+ flags.sort_by(|v1, v2| match v1.package_name.cmp(&v2.package_name) {
+ Ordering::Equal => v1.flag_name.cmp(&v2.flag_name),
other => other,
});
Ok(flags)
}
+/// Flag value and info summary
+#[derive(Debug, PartialEq)]
+pub struct FlagValueAndInfoSummary {
+ pub package_name: String,
+ pub flag_name: String,
+ pub flag_value: String,
+ pub value_type: StoredFlagType,
+ pub is_readwrite: bool,
+ pub has_server_override: bool,
+ pub has_local_override: bool,
+}
+
+/// List flag values and info from storage files
+pub fn list_flags_with_info(
+ package_map: &str,
+ flag_map: &str,
+ flag_val: &str,
+ flag_info: &str,
+) -> Result<Vec<FlagValueAndInfoSummary>, 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)?)?;
+ let flag_info = FlagInfoList::from_bytes(&read_file_to_bytes(flag_info)?)?;
+
+ let mut package_info = vec![("", 0); package_table.header.num_packages as usize];
+ for node in package_table.nodes.iter() {
+ package_info[node.package_id as usize] = (&node.package_name, node.boolean_start_index);
+ }
+
+ let mut flags = Vec::new();
+ for node in flag_table.nodes.iter() {
+ let (package_name, boolean_start_index) = package_info[node.package_id as usize];
+ let flag_index = boolean_start_index + node.flag_index as u32;
+ let flag_value = flag_value_list.booleans[flag_index as usize];
+ let flag_attribute = flag_info.nodes[flag_index as usize].attributes;
+ flags.push(FlagValueAndInfoSummary {
+ package_name: String::from(package_name),
+ flag_name: node.flag_name.clone(),
+ flag_value: flag_value.to_string(),
+ value_type: node.flag_type,
+ is_readwrite: flag_attribute & (FlagInfoBit::IsReadWrite as u8) != 0,
+ has_server_override: flag_attribute & (FlagInfoBit::HasServerOverride as u8) != 0,
+ has_local_override: flag_attribute & (FlagInfoBit::HasLocalOverride as u8) != 0,
+ });
+ }
+
+ flags.sort_by(|v1, v2| match v1.package_name.cmp(&v2.package_name) {
+ Ordering::Equal => v1.flag_name.cmp(&v2.flag_name),
+ other => other,
+ });
+ Ok(flags)
+}
+
+// *************************************** //
+// CC INTERLOP
+// *************************************** //
+
+// Exported rust data structure and methods, c++ code will be generated
+#[cxx::bridge]
+mod ffi {
+ /// flag value and info summary cxx return
+ pub struct FlagValueAndInfoSummaryCXX {
+ pub package_name: String,
+ pub flag_name: String,
+ pub flag_value: String,
+ pub value_type: String,
+ pub is_readwrite: bool,
+ pub has_server_override: bool,
+ pub has_local_override: bool,
+ }
+
+ /// list flag result cxx return
+ pub struct ListFlagValueAndInfoResultCXX {
+ pub query_success: bool,
+ pub error_message: String,
+ pub flags: Vec<FlagValueAndInfoSummaryCXX>,
+ }
+
+ // Rust export to c++
+ extern "Rust" {
+ pub fn list_flags_with_info_cxx(
+ package_map: &str,
+ flag_map: &str,
+ flag_val: &str,
+ flag_info: &str,
+ ) -> ListFlagValueAndInfoResultCXX;
+ }
+}
+
+/// implement flag value and info summary cxx return type
+impl ffi::FlagValueAndInfoSummaryCXX {
+ pub(crate) fn new(summary: FlagValueAndInfoSummary) -> Self {
+ Self {
+ package_name: summary.package_name,
+ flag_name: summary.flag_name,
+ flag_value: summary.flag_value,
+ value_type: format!("{:?}", summary.value_type),
+ is_readwrite: summary.is_readwrite,
+ has_server_override: summary.has_server_override,
+ has_local_override: summary.has_local_override,
+ }
+ }
+}
+
+/// implement list flag with info cxx interlop
+pub fn list_flags_with_info_cxx(
+ package_map: &str,
+ flag_map: &str,
+ flag_val: &str,
+ flag_info: &str,
+) -> ffi::ListFlagValueAndInfoResultCXX {
+ match list_flags_with_info(package_map, flag_map, flag_val, flag_info) {
+ Ok(summary) => ffi::ListFlagValueAndInfoResultCXX {
+ query_success: true,
+ error_message: String::new(),
+ flags: summary.into_iter().map(ffi::FlagValueAndInfoSummaryCXX::new).collect(),
+ },
+ Err(errmsg) => ffi::ListFlagValueAndInfoResultCXX {
+ query_success: false,
+ error_message: format!("{:?}", errmsg),
+ flags: Vec::new(),
+ },
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::{
- create_test_flag_table, create_test_flag_value_list, create_test_package_table,
- write_bytes_to_temp_file,
+ create_test_flag_info_list, create_test_flag_table, create_test_flag_value_list,
+ create_test_package_table, write_bytes_to_temp_file,
};
#[test]
@@ -337,54 +471,154 @@ mod tests {
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"),
- String::from("disabled_rw"),
- StoredFlagType::ReadWriteBoolean,
- false,
- ),
- (
- String::from("com.android.aconfig.storage.test_1"),
- String::from("enabled_ro"),
- StoredFlagType::ReadOnlyBoolean,
- true,
- ),
- (
- String::from("com.android.aconfig.storage.test_1"),
- String::from("enabled_rw"),
- StoredFlagType::ReadWriteBoolean,
- true,
- ),
- (
- String::from("com.android.aconfig.storage.test_2"),
- String::from("disabled_rw"),
- StoredFlagType::ReadWriteBoolean,
- false,
- ),
- (
- String::from("com.android.aconfig.storage.test_2"),
- String::from("enabled_fixed_ro"),
- StoredFlagType::FixedReadOnlyBoolean,
- true,
- ),
- (
- String::from("com.android.aconfig.storage.test_2"),
- String::from("enabled_ro"),
- StoredFlagType::ReadOnlyBoolean,
- true,
- ),
- (
- String::from("com.android.aconfig.storage.test_4"),
- String::from("enabled_fixed_ro"),
- StoredFlagType::FixedReadOnlyBoolean,
- true,
- ),
- (
- String::from("com.android.aconfig.storage.test_4"),
- String::from("enabled_rw"),
- StoredFlagType::ReadWriteBoolean,
- true,
- ),
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ flag_name: String::from("disabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("false"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ flag_name: String::from("enabled_ro"),
+ value_type: StoredFlagType::ReadOnlyBoolean,
+ flag_value: String::from("true"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ flag_name: String::from("enabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("true"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ flag_name: String::from("disabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("false"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ flag_name: String::from("enabled_fixed_ro"),
+ value_type: StoredFlagType::FixedReadOnlyBoolean,
+ flag_value: String::from("true"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ flag_name: String::from("enabled_ro"),
+ value_type: StoredFlagType::ReadOnlyBoolean,
+ flag_value: String::from("true"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_4"),
+ flag_name: String::from("enabled_fixed_ro"),
+ value_type: StoredFlagType::FixedReadOnlyBoolean,
+ flag_value: String::from("true"),
+ },
+ FlagValueSummary {
+ package_name: String::from("com.android.aconfig.storage.test_4"),
+ flag_name: String::from("enabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("true"),
+ },
+ ];
+ assert_eq!(flags, expected);
+ }
+
+ #[test]
+ // this test point locks down the flag list with info api
+ fn test_list_flag_with_info() {
+ let package_table =
+ write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap();
+ let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap();
+ let flag_value_list =
+ write_bytes_to_temp_file(&create_test_flag_value_list().into_bytes()).unwrap();
+ let flag_info_list =
+ write_bytes_to_temp_file(&create_test_flag_info_list().into_bytes()).unwrap();
+
+ let package_table_path = package_table.path().display().to_string();
+ let flag_table_path = flag_table.path().display().to_string();
+ let flag_value_list_path = flag_value_list.path().display().to_string();
+ let flag_info_list_path = flag_info_list.path().display().to_string();
+
+ let flags = list_flags_with_info(
+ &package_table_path,
+ &flag_table_path,
+ &flag_value_list_path,
+ &flag_info_list_path,
+ )
+ .unwrap();
+ let expected = [
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ flag_name: String::from("disabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("false"),
+ is_readwrite: true,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ flag_name: String::from("enabled_ro"),
+ value_type: StoredFlagType::ReadOnlyBoolean,
+ flag_value: String::from("true"),
+ is_readwrite: false,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ flag_name: String::from("enabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("true"),
+ is_readwrite: true,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ flag_name: String::from("disabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("false"),
+ is_readwrite: true,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ flag_name: String::from("enabled_fixed_ro"),
+ value_type: StoredFlagType::FixedReadOnlyBoolean,
+ flag_value: String::from("true"),
+ is_readwrite: false,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ flag_name: String::from("enabled_ro"),
+ value_type: StoredFlagType::ReadOnlyBoolean,
+ flag_value: String::from("true"),
+ is_readwrite: false,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_4"),
+ flag_name: String::from("enabled_fixed_ro"),
+ value_type: StoredFlagType::FixedReadOnlyBoolean,
+ flag_value: String::from("true"),
+ is_readwrite: false,
+ has_server_override: false,
+ has_local_override: false,
+ },
+ FlagValueAndInfoSummary {
+ package_name: String::from("com.android.aconfig.storage.test_4"),
+ flag_name: String::from("enabled_rw"),
+ value_type: StoredFlagType::ReadWriteBoolean,
+ flag_value: String::from("true"),
+ is_readwrite: true,
+ has_server_override: false,
+ has_local_override: false,
+ },
];
assert_eq!(flags, expected);
}
diff --git a/tools/aconfig/aconfig_storage_file/src/main.rs b/tools/aconfig/aconfig_storage_file/src/main.rs
index b686274a2d..8b9e38da02 100644
--- a/tools/aconfig/aconfig_storage_file/src/main.rs
+++ b/tools/aconfig/aconfig_storage_file/src/main.rs
@@ -17,8 +17,8 @@
//! `aconfig-storage` is a debugging tool to parse storage files
use aconfig_storage_file::{
- list_flags, read_file_to_bytes, AconfigStorageError, FlagInfoList, FlagTable, FlagValueList,
- PackageTable, StorageFileType,
+ list_flags, list_flags_with_info, read_file_to_bytes, AconfigStorageError, FlagInfoList,
+ FlagTable, FlagValueList, PackageTable, StorageFileType,
};
use clap::{builder::ArgAction, Arg, Command};
@@ -45,7 +45,10 @@ fn cli() -> Command {
.action(ArgAction::Set),
)
.arg(Arg::new("flag-map").long("flag-map").required(true).action(ArgAction::Set))
- .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set)),
+ .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set))
+ .arg(
+ Arg::new("flag-info").long("flag-info").required(false).action(ArgAction::Set),
+ ),
)
}
@@ -87,9 +90,27 @@ fn main() -> Result<(), AconfigStorageError> {
let package_map = sub_matches.get_one::<String>("package-map").unwrap();
let flag_map = sub_matches.get_one::<String>("flag-map").unwrap();
let flag_val = sub_matches.get_one::<String>("flag-val").unwrap();
- let flags = list_flags(package_map, flag_map, flag_val)?;
- for (package_name, flag_name, flag_type, flag_value) in flags.iter() {
- println!("{} {} {:?} {}", package_name, flag_name, flag_type, flag_value);
+ let flag_info = sub_matches.get_one::<String>("flag-info");
+ match flag_info {
+ Some(info_file) => {
+ let flags = list_flags_with_info(package_map, flag_map, flag_val, info_file)?;
+ for flag in flags.iter() {
+ println!(
+ "{} {} {} {:?} IsReadWrite: {}, HasServerOverride: {}, HasLocalOverride: {}",
+ flag.package_name, flag.flag_name, flag.flag_value, flag.value_type,
+ flag.is_readwrite, flag.has_server_override, flag.has_local_override,
+ );
+ }
+ }
+ None => {
+ let flags = list_flags(package_map, flag_map, flag_val)?;
+ for flag in flags.iter() {
+ println!(
+ "{} {} {} {:?}",
+ flag.package_name, flag.flag_name, flag.flag_value, flag.value_type,
+ );
+ }
+ }
}
}
_ => unreachable!(),
diff --git a/tools/aconfig/aconfig_storage_file/tests/Android.bp b/tools/aconfig/aconfig_storage_file/tests/Android.bp
new file mode 100644
index 0000000000..26b7800877
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/Android.bp
@@ -0,0 +1,23 @@
+
+cc_test {
+ name: "aconfig_storage_file.test.cpp",
+ team: "trendy_team_android_core_experiments",
+ srcs: [
+ "storage_file_test.cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ "libaconfig_storage_file_cc",
+ "libbase",
+ ],
+ data: [
+ "package.map",
+ "flag.map",
+ "flag.val",
+ "flag.info",
+ ],
+ test_suites: [
+ "device-tests",
+ "general-tests",
+ ],
+}
diff --git a/tools/aconfig/aconfig_storage_file/tests/flag.info b/tools/aconfig/aconfig_storage_file/tests/flag.info
new file mode 100644
index 0000000000..6223edf369
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/flag.info
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/flag.map b/tools/aconfig/aconfig_storage_file/tests/flag.map
new file mode 100644
index 0000000000..e868f53d7e
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/flag.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/flag.val b/tools/aconfig/aconfig_storage_file/tests/flag.val
new file mode 100644
index 0000000000..ed203d4d13
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/flag.val
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/package.map b/tools/aconfig/aconfig_storage_file/tests/package.map
new file mode 100644
index 0000000000..6c46a0339c
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/package.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
new file mode 100644
index 0000000000..eccbca53d5
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <vector>
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <gtest/gtest.h>
+#include "aconfig_storage/aconfig_storage_file.hpp"
+
+using namespace android::base;
+using namespace aconfig_storage;
+
+
+void verify_flag(const FlagValueAndInfoSummary& flag,
+ const std::string& package_name,
+ const std::string& flag_name,
+ const std::string& flag_val,
+ const std::string& value_type,
+ bool is_readwrite,
+ bool has_server_override,
+ bool has_local_override) {
+ ASSERT_EQ(flag.package_name, package_name);
+ ASSERT_EQ(flag.flag_name, flag_name);
+ ASSERT_EQ(flag.flag_value, flag_val);
+ ASSERT_EQ(flag.value_type, value_type);
+ ASSERT_EQ(flag.is_readwrite, is_readwrite);
+ ASSERT_EQ(flag.has_server_override, has_server_override);
+ ASSERT_EQ(flag.has_local_override, has_local_override);
+}
+
+TEST(AconfigStorageFileTest, test_list_flag_with_info) {
+ auto const test_dir = GetExecutableDirectory();
+ auto const package_map = test_dir + "/package.map";
+ auto const flag_map = test_dir + "/flag.map";
+ auto const flag_val = test_dir + "/flag.val";
+ auto const flag_info = test_dir + "/flag.info";
+ auto flag_list_result = aconfig_storage::list_flags_with_info(
+ package_map, flag_map, flag_val, flag_info);
+ ASSERT_TRUE(flag_list_result.ok());
+
+ auto const& flag_list = *flag_list_result;
+ ASSERT_EQ(flag_list.size(), 8);
+ verify_flag(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw",
+ "false", "ReadWriteBoolean", true, false, false);
+ verify_flag(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro",
+ "true", "ReadOnlyBoolean", false, false, false);
+ verify_flag(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw",
+ "true", "ReadWriteBoolean", true, false, false);
+ verify_flag(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw",
+ "false", "ReadWriteBoolean", true, false, false);
+ verify_flag(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro",
+ "true", "FixedReadOnlyBoolean", false, false, false);
+ verify_flag(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro",
+ "true", "ReadOnlyBoolean", false, false, false);
+ verify_flag(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro",
+ "true", "FixedReadOnlyBoolean", false, false, false);
+ verify_flag(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw",
+ "true", "ReadWriteBoolean", true, false, false);
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index e65dcfbc69..e4192066d5 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -504,7 +504,7 @@ files {{
let pb_file_path = pb_file.path().display().to_string();
let flag_info_file =
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
- let is_rw: Vec<bool> = vec![true, false, true, false, false, false, false, false];
+ let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true];
for (offset, expected_value) in is_rw.into_iter().enumerate() {
let attribute =
get_flag_attribute(&flag_info_file, FlagValueType::Boolean, offset as u32).unwrap();
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/flag.info b/tools/aconfig/aconfig_storage_read_api/tests/flag.info
index 820d839363..6223edf369 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/flag.info
+++ b/tools/aconfig/aconfig_storage_read_api/tests/flag.info
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
index b499c1c279..cfd128d123 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
@@ -232,7 +232,7 @@ TEST_F(AconfigStorageTest, test_boolean_flag_info_query) {
ASSERT_TRUE(mapped_file.ok());
auto expected_value = std::vector<bool>{
- true, false, true, false, false, false, false, false};
+ true, false, true, true, false, false, false, true};
for (int index = 0; index < 8; ++index) {
auto attribute = api::get_flag_attribute(*mapped_file, api::FlagValueType::Boolean, index);
ASSERT_TRUE(attribute.ok());
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
index ce9c0186dd..ecba573d82 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
@@ -188,7 +188,7 @@ files {{
// The safety here is ensured as the test process will not write to temp storage file
let flag_info_file =
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
- let is_rw: Vec<bool> = vec![true, false, true, false, false, false, false, false];
+ let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true];
for (offset, expected_value) in is_rw.into_iter().enumerate() {
let attribute =
get_flag_attribute(&flag_info_file, FlagValueType::Boolean, offset as u32).unwrap();
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index a3ca221d9e..c21c5424bb 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -27,13 +27,13 @@ impl FlagSource for AconfigStorageSource {
let container =
file_info.container.ok_or(anyhow!("storage file is missing container"))?;
- for (package, name, _flag_type, val) in
+ for listed_flag 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())?,
+ name: listed_flag.flag_name,
+ package: listed_flag.package_name,
+ value: FlagValue::try_from(listed_flag.flag_value.as_str())?,
container: container.to_string(),
// TODO(b/324436145): delete namespace field once DeviceConfig isn't in CLI.