Merge "Fix numeric selection from lunch menu" into main
diff --git a/core/base_rules.mk b/core/base_rules.mk
index a446483..254bfeb 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -121,9 +121,17 @@
$(LOCAL_PROPRIETARY_MODULE))
include $(BUILD_SYSTEM)/local_vndk.mk
-include $(BUILD_SYSTEM)/local_systemsdk.mk
+
+# local_current_sdk needs to run before local_systemsdk because the former may override
+# LOCAL_SDK_VERSION which is used by the latter.
include $(BUILD_SYSTEM)/local_current_sdk.mk
+# Check if the use of System SDK is correct. Note that, for Soong modules, the system sdk version
+# check is done in Soong. No need to do it twice.
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+include $(BUILD_SYSTEM)/local_systemsdk.mk
+endif
+
# Ninja has an implicit dependency on the command being run, and kati will
# regenerate the ninja manifest if any read makefile changes, so there is no
# need to have dependencies on makefiles.
diff --git a/core/board_config.mk b/core/board_config.mk
index ae11eb6..5a1a781 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -186,6 +186,7 @@
BUILD_BROKEN_VINTF_PRODUCT_COPY_FILES \
BUILD_BROKEN_INCORRECT_PARTITION_IMAGES \
BUILD_BROKEN_GENRULE_SANDBOXING \
+ BUILD_BROKEN_DONT_CHECK_SYSTEMSDK \
_build_broken_var_list += \
$(foreach m,$(AVAILABLE_BUILD_MODULE_TYPES) \
diff --git a/core/local_current_sdk.mk b/core/local_current_sdk.mk
index ea7da8a..ccdbf77 100644
--- a/core/local_current_sdk.mk
+++ b/core/local_current_sdk.mk
@@ -14,13 +14,24 @@
# limitations under the License.
#
ifdef BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES
- ifneq (current,$(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES))
+ _override_to := $(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES)
+
+ # b/314011075: apks and jars in the vendor or odm partitions cannot use
+ # system SDK 35 and beyond. In order not to suddenly break those vendor
+ # modules using current or system_current as their LOCAL_SDK_VERSION,
+ # override it to 34, which is the maximum API level allowed for them.
+ ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
+ _override_to := 34
+ endif
+
+ ifneq (current,$(_override_to))
ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
ifeq (current,$(LOCAL_SDK_VERSION))
- LOCAL_SDK_VERSION := $(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES)
+ LOCAL_SDK_VERSION := $(_override_to)
else ifeq (system_current,$(LOCAL_SDK_VERSION))
- LOCAL_SDK_VERSION := system_$(BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES)
+ LOCAL_SDK_VERSION := system_$(_override_to)
endif
endif
endif
+ _override_to :=
endif
diff --git a/core/local_systemsdk.mk b/core/local_systemsdk.mk
index 460073d..3307e72 100644
--- a/core/local_systemsdk.mk
+++ b/core/local_systemsdk.mk
@@ -33,6 +33,9 @@
# Runtime resource overlays are exempted from building against System SDK.
# TODO(b/155027019): remove this, after no product/vendor apps rely on this behavior.
LOCAL_SDK_VERSION := system_current
+ # We have run below again since LOCAL_SDK_VERSION is newly set and the "_current"
+ # may have to be updated
+ include $(BUILD_SYSTEM)/local_current_sdk.mk
endif
endif
endif
@@ -54,10 +57,35 @@
# If not, vendor apks are treated equally to system apps
_supported_systemsdk_versions := $(PLATFORM_SYSTEMSDK_VERSIONS)
endif
+
+ # b/314011075: apks and jars in the vendor or odm partitions cannot use system SDK 35 and beyond.
+ # This is to discourage the use of Java APIs in the partitions, which hasn't been supported since
+ # the beginning of the project Treble back in Android 10. Ultimately, we'd like to completely
+ # disallow any Java API in the partitions, but it shall be done progressively.
+ ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
+ # 28 is the API level when BOARD_SYSTEMSDK_VERSIONS was introduced. So, it's the oldset API
+ # we allow.
+ _supported_systemsdk_versions := $(call int_range_list, 28, 34)
+ endif
+
+ # Extract version number from LOCAL_SDK_VERSION (ex: system_34 -> 34)
_system_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
+ # However, the extraction may fail if it doesn't have any number (i.e. current, core_current,
+ # system_current, or similar) Then use the latest platform SDK version number or the actual
+ # codename.
+ ifeq (,$(_system_sdk_version)
+ ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ _system_sdk_version := $(PLATFORM_SDK_VERSION)
+ else
+ _system_sdk_version := $(PLATFORM_VERSION_CODENAME)
+ endif
+ endif
+
ifneq ($(_system_sdk_version),$(filter $(_system_sdk_version),$(_supported_systemsdk_versions)))
- $(call pretty-error,Incompatible LOCAL_SDK_VERSION '$(LOCAL_SDK_VERSION)'. \
- System SDK version '$(_system_sdk_version)' is not supported. Supported versions are: $(_supported_systemsdk_versions))
+ ifneq (true,$(BUILD_BROKEN_DONT_CHECK_SYSTEMSDK)
+ $(call pretty-error,Incompatible LOCAL_SDK_VERSION '$(LOCAL_SDK_VERSION)'. \
+ System SDK version '$(_system_sdk_version)' is not supported. Supported versions are: $(_supported_systemsdk_versions))
+ endif
endif
_system_sdk_version :=
_supported_systemsdk_versions :=
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 193ac18..b6ce2a7 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -299,6 +299,7 @@
$(call add_json_bool, BuildBrokenVendorPropertyNamespace, $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
$(call add_json_bool, BuildBrokenIncorrectPartitionImages, $(filter true,$(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES)))
$(call add_json_list, BuildBrokenInputDirModules, $(BUILD_BROKEN_INPUT_DIR_MODULES))
+$(call add_json_bool, BuildBrokenDontCheckSystemSdk, $(filter true,$(BUILD_BROKEN_DONT_CHECK_SYSTEMSDK)))
$(call add_json_list, BuildWarningBadOptionalUsesLibsAllowlist, $(BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST))
diff --git a/envsetup.sh b/envsetup.sh
index 84a604c..5aa11c7 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -775,7 +775,7 @@
answer=$1
else
print_lunch_menu
- echo "Which would you like? [aosp_arm-trunk_staging-eng]"
+ echo "Which would you like? [aosp_cf_x86_64_phone-trunk_staging-eng]"
echo -n "Pick from common choices above (e.g. 13) or specify your own (e.g. aosp_barbet-trunk_staging-eng): "
read answer
used_lunch_menu=1
@@ -785,7 +785,7 @@
if [ -z "$answer" ]
then
- selection=aosp_arm-trunk_staging-eng
+ selection=aosp_cf_x86_64_phone-trunk_staging-eng
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
then
local choices=($(TARGET_BUILD_APPS= TARGET_PRODUCT= TARGET_RELEASE= TARGET_BUILD_VARIANT= get_build_var COMMON_LUNCH_CHOICES 2>/dev/null))
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 53c9e0c..80aecb7 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -18,6 +18,7 @@
LLNDK: libneuralnetworks.so
LLNDK: libselinux.so
LLNDK: libsync.so
+LLNDK: libvendorsupport.so
LLNDK: libvndksupport.so
LLNDK: libvulkan.so
VNDK-SP: android.hardware.common-V2-ndk.so
diff --git a/tools/aconfig/Cargo.toml b/tools/aconfig/Cargo.toml
index 2edf4b8..7b58e94 100644
--- a/tools/aconfig/Cargo.toml
+++ b/tools/aconfig/Cargo.toml
@@ -20,6 +20,3 @@
[build-dependencies]
protobuf-codegen = "3.2.0"
-
-[dev-dependencies]
-itertools = "0.10.5"
diff --git a/tools/aconfig/src/codegen/java.rs b/tools/aconfig/src/codegen/java.rs
index f214fa5..78e892b 100644
--- a/tools/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/src/codegen/java.rs
@@ -925,7 +925,7 @@
public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
/** @hide */
public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
-
+
@com.android.aconfig.annotations.AssumeFalseForR8
@UnsupportedAppUsage
public static boolean disabledRo() {
diff --git a/tools/aconfig/src/codegen/mod.rs b/tools/aconfig/src/codegen/mod.rs
index 4af1327..64ffa8b 100644
--- a/tools/aconfig/src/codegen/mod.rs
+++ b/tools/aconfig/src/codegen/mod.rs
@@ -44,7 +44,7 @@
}
pub fn is_valid_container_ident(s: &str) -> bool {
- is_valid_name_ident(s) || s.split('.').all(is_valid_name_ident)
+ s.split('.').all(is_valid_name_ident)
}
pub fn create_device_config_ident(package: &str, flag_name: &str) -> Result<String> {
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index ffd89a3..1a8872b 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -361,7 +361,7 @@
Ok(modified_parsed_flags)
}
-fn assign_flag_ids<'a, I>(package: &str, parsed_flags_iter: I) -> Result<HashMap<String, u32>>
+pub fn assign_flag_ids<'a, I>(package: &str, parsed_flags_iter: I) -> Result<HashMap<String, u32>>
where
I: Iterator<Item = &'a ProtoParsedFlag> + Clone,
{
diff --git a/tools/aconfig/src/storage/flag_table.rs b/tools/aconfig/src/storage/flag_table.rs
new file mode 100644
index 0000000..46753f0
--- /dev/null
+++ b/tools/aconfig/src/storage/flag_table.rs
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ */
+
+use crate::commands::assign_flag_ids;
+use crate::storage::{self, FlagPackage};
+use anyhow::{anyhow, Result};
+
+#[derive(PartialEq, Debug)]
+pub struct FlagTableHeader {
+ pub version: u32,
+ pub container: String,
+ pub file_size: u32,
+ pub num_flags: u32,
+ pub bucket_offset: u32,
+ pub node_offset: u32,
+}
+
+impl FlagTableHeader {
+ fn new(container: &str, num_flags: u32) -> Self {
+ Self {
+ version: storage::FILE_VERSION,
+ container: String::from(container),
+ file_size: 0,
+ num_flags,
+ bucket_offset: 0,
+ node_offset: 0,
+ }
+ }
+
+ fn as_bytes(&self) -> Vec<u8> {
+ let mut result = Vec::new();
+ result.extend_from_slice(&self.version.to_le_bytes());
+ let container_bytes = self.container.as_bytes();
+ result.extend_from_slice(&(container_bytes.len() as u32).to_le_bytes());
+ result.extend_from_slice(container_bytes);
+ result.extend_from_slice(&self.file_size.to_le_bytes());
+ result.extend_from_slice(&self.num_flags.to_le_bytes());
+ result.extend_from_slice(&self.bucket_offset.to_le_bytes());
+ result.extend_from_slice(&self.node_offset.to_le_bytes());
+ result
+ }
+}
+
+#[derive(PartialEq, Debug, Clone)]
+pub struct FlagTableNode {
+ pub package_id: u32,
+ pub flag_name: String,
+ pub flag_id: u32,
+ pub next_offset: Option<u32>,
+ pub bucket_index: u32,
+}
+
+impl FlagTableNode {
+ fn new(package_id: u32, flag_name: &str, flag_id: u32, num_buckets: u32) -> Self {
+ let full_flag_name = package_id.to_string() + "/" + flag_name;
+ let bucket_index = storage::get_bucket_index(&full_flag_name, num_buckets);
+ Self {
+ package_id,
+ flag_name: flag_name.to_string(),
+ flag_id,
+ next_offset: None,
+ bucket_index,
+ }
+ }
+
+ fn as_bytes(&self) -> Vec<u8> {
+ let mut result = Vec::new();
+ result.extend_from_slice(&self.package_id.to_le_bytes());
+ let name_bytes = self.flag_name.as_bytes();
+ result.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
+ result.extend_from_slice(name_bytes);
+ result.extend_from_slice(&self.flag_id.to_le_bytes());
+ result.extend_from_slice(&self.next_offset.unwrap_or(0).to_le_bytes());
+ result
+ }
+}
+
+#[derive(PartialEq, Debug)]
+pub struct FlagTable {
+ pub header: FlagTableHeader,
+ pub buckets: Vec<Option<u32>>,
+ pub nodes: Vec<FlagTableNode>,
+}
+
+impl FlagTable {
+ fn create_nodes(package: &FlagPackage, num_buckets: u32) -> Result<Vec<FlagTableNode>> {
+ let flag_names = package.boolean_flags.iter().map(|pf| pf.name()).collect::<Vec<_>>();
+ println!("{:?}", flag_names);
+ let flag_ids =
+ assign_flag_ids(package.package_name, package.boolean_flags.iter().copied())?;
+ package
+ .boolean_flags
+ .iter()
+ .map(|&pf| {
+ let fid = flag_ids
+ .get(pf.name())
+ .ok_or(anyhow!(format!("missing flag id for {}", pf.name())))?;
+ Ok(FlagTableNode::new(package.package_id, pf.name(), *fid, num_buckets))
+ })
+ .collect::<Result<Vec<_>>>()
+ }
+
+ pub fn new(container: &str, packages: &[FlagPackage]) -> Result<Self> {
+ // create table
+ let num_flags = packages.iter().map(|pkg| pkg.boolean_flags.len() as u32).sum();
+ let num_buckets = storage::get_table_size(num_flags)?;
+
+ let mut table = Self {
+ header: FlagTableHeader::new(container, num_flags),
+ buckets: vec![None; num_buckets as usize],
+ nodes: packages
+ .iter()
+ .map(|pkg| FlagTable::create_nodes(pkg, num_buckets))
+ .collect::<Result<Vec<_>>>()?
+ .concat(),
+ };
+
+ // initialize all header fields
+ table.header.bucket_offset = table.header.as_bytes().len() as u32;
+ table.header.node_offset = table.header.bucket_offset + num_buckets * 4;
+ table.header.file_size = table.header.node_offset
+ + table.nodes.iter().map(|x| x.as_bytes().len()).sum::<usize>() as u32;
+
+ // sort nodes by bucket index for efficiency
+ table.nodes.sort_by(|a, b| a.bucket_index.cmp(&b.bucket_index));
+
+ // fill all node offset
+ let mut offset = table.header.node_offset;
+ for i in 0..table.nodes.len() {
+ let node_bucket_idx = table.nodes[i].bucket_index;
+ let next_node_bucket_idx = if i + 1 < table.nodes.len() {
+ Some(table.nodes[i + 1].bucket_index)
+ } else {
+ None
+ };
+
+ if table.buckets[node_bucket_idx as usize].is_none() {
+ table.buckets[node_bucket_idx as usize] = Some(offset);
+ }
+ offset += table.nodes[i].as_bytes().len() as u32;
+
+ if let Some(index) = next_node_bucket_idx {
+ if index == node_bucket_idx {
+ table.nodes[i].next_offset = Some(offset);
+ }
+ }
+ }
+
+ Ok(table)
+ }
+
+ pub fn as_bytes(&self) -> Vec<u8> {
+ [
+ self.header.as_bytes(),
+ self.buckets.iter().map(|v| v.unwrap_or(0).to_le_bytes()).collect::<Vec<_>>().concat(),
+ self.nodes.iter().map(|v| v.as_bytes()).collect::<Vec<_>>().concat(),
+ ]
+ .concat()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::storage::{
+ group_flags_by_package, tests::parse_all_test_flags, tests::read_str_from_bytes,
+ tests::read_u32_from_bytes,
+ };
+
+ impl FlagTableHeader {
+ // test only method to deserialize back into the header struct
+ fn from_bytes(bytes: &[u8]) -> Result<Self> {
+ let mut head = 0;
+ Ok(Self {
+ version: read_u32_from_bytes(bytes, &mut head)?,
+ container: read_str_from_bytes(bytes, &mut head)?,
+ file_size: read_u32_from_bytes(bytes, &mut head)?,
+ num_flags: read_u32_from_bytes(bytes, &mut head)?,
+ bucket_offset: read_u32_from_bytes(bytes, &mut head)?,
+ node_offset: read_u32_from_bytes(bytes, &mut head)?,
+ })
+ }
+ }
+
+ impl FlagTableNode {
+ // test only method to deserialize back into the node struct
+ fn from_bytes(bytes: &[u8], num_buckets: u32) -> Result<Self> {
+ let mut head = 0;
+ let mut node = Self {
+ package_id: read_u32_from_bytes(bytes, &mut head)?,
+ flag_name: read_str_from_bytes(bytes, &mut head)?,
+ flag_id: read_u32_from_bytes(bytes, &mut head)?,
+ next_offset: match read_u32_from_bytes(bytes, &mut head)? {
+ 0 => None,
+ val => Some(val),
+ },
+ bucket_index: 0,
+ };
+ let full_flag_name = node.package_id.to_string() + "/" + &node.flag_name;
+ node.bucket_index = storage::get_bucket_index(&full_flag_name, num_buckets);
+ Ok(node)
+ }
+
+ // create test baseline, syntactic sugar
+ fn new_expected(
+ package_id: u32,
+ flag_name: &str,
+ flag_id: u32,
+ next_offset: Option<u32>,
+ bucket_index: u32,
+ ) -> Self {
+ Self {
+ package_id,
+ flag_name: flag_name.to_string(),
+ flag_id,
+ next_offset,
+ bucket_index,
+ }
+ }
+ }
+
+ impl FlagTable {
+ // test only method to deserialize back into the table struct
+ fn from_bytes(bytes: &[u8]) -> Result<Self> {
+ let header = FlagTableHeader::from_bytes(bytes)?;
+ let num_flags = header.num_flags;
+ let num_buckets = storage::get_table_size(num_flags)?;
+ let mut head = header.as_bytes().len();
+ let buckets = (0..num_buckets)
+ .map(|_| match read_u32_from_bytes(bytes, &mut head).unwrap() {
+ 0 => None,
+ val => Some(val),
+ })
+ .collect();
+ let nodes = (0..num_flags)
+ .map(|_| {
+ let node = FlagTableNode::from_bytes(&bytes[head..], num_buckets).unwrap();
+ head += node.as_bytes().len();
+ node
+ })
+ .collect();
+
+ let table = Self { header, buckets, nodes };
+ Ok(table)
+ }
+ }
+
+ pub fn create_test_flag_table() -> Result<FlagTable> {
+ let caches = parse_all_test_flags();
+ let packages = group_flags_by_package(caches.iter());
+ FlagTable::new("system", &packages)
+ }
+
+ #[test]
+ // this test point locks down the table creation and each field
+ fn test_table_contents() {
+ let flag_table = create_test_flag_table();
+ assert!(flag_table.is_ok());
+
+ let header: &FlagTableHeader = &flag_table.as_ref().unwrap().header;
+ let expected_header = FlagTableHeader {
+ version: storage::FILE_VERSION,
+ container: String::from("system"),
+ file_size: 320,
+ num_flags: 8,
+ bucket_offset: 30,
+ node_offset: 98,
+ };
+ assert_eq!(header, &expected_header);
+
+ println!("{:?}", &flag_table.as_ref().unwrap().nodes);
+
+ let buckets: &Vec<Option<u32>> = &flag_table.as_ref().unwrap().buckets;
+ let expected_bucket: Vec<Option<u32>> = vec![
+ Some(98),
+ Some(124),
+ None,
+ None,
+ None,
+ Some(177),
+ None,
+ Some(203),
+ None,
+ Some(261),
+ None,
+ None,
+ None,
+ None,
+ None,
+ Some(293),
+ None,
+ ];
+ assert_eq!(buckets, &expected_bucket);
+
+ let nodes: &Vec<FlagTableNode> = &flag_table.as_ref().unwrap().nodes;
+ assert_eq!(nodes.len(), 8);
+
+ assert_eq!(nodes[0], FlagTableNode::new_expected(0, "enabled_ro", 1, None, 0));
+ assert_eq!(nodes[1], FlagTableNode::new_expected(0, "enabled_rw", 2, Some(150), 1));
+ assert_eq!(nodes[2], FlagTableNode::new_expected(1, "disabled_ro", 0, None, 1));
+ assert_eq!(nodes[3], FlagTableNode::new_expected(2, "enabled_ro", 1, None, 5));
+ assert_eq!(nodes[4], FlagTableNode::new_expected(1, "enabled_fixed_ro", 1, Some(235), 7));
+ assert_eq!(nodes[5], FlagTableNode::new_expected(1, "enabled_ro", 2, None, 7));
+ assert_eq!(nodes[6], FlagTableNode::new_expected(2, "enabled_fixed_ro", 0, None, 9));
+ assert_eq!(nodes[7], FlagTableNode::new_expected(0, "disabled_rw", 0, None, 15));
+ }
+
+ #[test]
+ // this test point locks down the table serialization
+ fn test_serialization() {
+ let flag_table = create_test_flag_table();
+ assert!(flag_table.is_ok());
+ let flag_table = flag_table.unwrap();
+
+ let header: &FlagTableHeader = &flag_table.header;
+ let reinterpreted_header = FlagTableHeader::from_bytes(&header.as_bytes());
+ assert!(reinterpreted_header.is_ok());
+ assert_eq!(header, &reinterpreted_header.unwrap());
+
+ let nodes: &Vec<FlagTableNode> = &flag_table.nodes;
+ let num_buckets = storage::get_table_size(header.num_flags).unwrap();
+ for node in nodes.iter() {
+ let reinterpreted_node = FlagTableNode::from_bytes(&node.as_bytes(), num_buckets);
+ assert!(reinterpreted_node.is_ok());
+ assert_eq!(node, &reinterpreted_node.unwrap());
+ }
+
+ let reinterpreted_table = FlagTable::from_bytes(&flag_table.as_bytes());
+ assert!(reinterpreted_table.is_ok());
+ assert_eq!(&flag_table, &reinterpreted_table.unwrap());
+ }
+}
diff --git a/tools/aconfig/src/storage/mod.rs b/tools/aconfig/src/storage/mod.rs
index 686f9ae..76835e0 100644
--- a/tools/aconfig/src/storage/mod.rs
+++ b/tools/aconfig/src/storage/mod.rs
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+pub mod flag_table;
pub mod package_table;
use anyhow::{anyhow, Result};
@@ -23,12 +24,12 @@
use crate::commands::OutputFile;
use crate::protos::{ProtoParsedFlag, ProtoParsedFlags};
-use crate::storage::package_table::PackageTable;
+use crate::storage::{flag_table::FlagTable, package_table::PackageTable};
pub const FILE_VERSION: u32 = 1;
pub const HASH_PRIMES: [u32; 29] = [
- 7, 13, 29, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241,
+ 7, 17, 29, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241,
786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611,
402653189, 805306457, 1610612741,
];
@@ -120,7 +121,13 @@
let package_table_file =
OutputFile { contents: package_table.as_bytes(), path: package_table_file_path };
- Ok(vec![package_table_file])
+ // create and serialize flag map
+ let flag_table = FlagTable::new(container, &packages)?;
+ let flag_table_file_path = PathBuf::from("flag.map");
+ let flag_table_file =
+ OutputFile { contents: flag_table.as_bytes(), path: flag_table_file_path };
+
+ Ok(vec![package_table_file, flag_table_file])
}
#[cfg(test)]
@@ -147,13 +154,8 @@
let aconfig_files = [
(
"com.android.aconfig.storage.test_1",
- "storage_test_1_part_1.aconfig",
- include_bytes!("../../tests/storage_test_1_part_1.aconfig").as_slice(),
- ),
- (
- "com.android.aconfig.storage.test_1",
- "storage_test_1_part_2.aconfig",
- include_bytes!("../../tests/storage_test_1_part_2.aconfig").as_slice(),
+ "storage_test_1.aconfig",
+ include_bytes!("../../tests/storage_test_1.aconfig").as_slice(),
),
(
"com.android.aconfig.storage.test_2",
@@ -204,12 +206,10 @@
assert_eq!(packages[0].package_name, "com.android.aconfig.storage.test_1");
assert_eq!(packages[0].package_id, 0);
- assert_eq!(packages[0].flag_names.len(), 5);
+ assert_eq!(packages[0].flag_names.len(), 3);
assert!(packages[0].flag_names.contains("enabled_rw"));
assert!(packages[0].flag_names.contains("disabled_rw"));
assert!(packages[0].flag_names.contains("enabled_ro"));
- assert!(packages[0].flag_names.contains("disabled_ro"));
- assert!(packages[0].flag_names.contains("enabled_fixed_ro"));
assert_eq!(packages[0].boolean_offset, 0);
assert_eq!(packages[1].package_name, "com.android.aconfig.storage.test_2");
@@ -218,13 +218,13 @@
assert!(packages[1].flag_names.contains("enabled_ro"));
assert!(packages[1].flag_names.contains("disabled_ro"));
assert!(packages[1].flag_names.contains("enabled_fixed_ro"));
- assert_eq!(packages[1].boolean_offset, 10);
+ assert_eq!(packages[1].boolean_offset, 6);
assert_eq!(packages[2].package_name, "com.android.aconfig.storage.test_4");
assert_eq!(packages[2].package_id, 2);
assert_eq!(packages[2].flag_names.len(), 2);
assert!(packages[2].flag_names.contains("enabled_ro"));
assert!(packages[2].flag_names.contains("enabled_fixed_ro"));
- assert_eq!(packages[2].boolean_offset, 16);
+ assert_eq!(packages[2].boolean_offset, 12);
}
}
diff --git a/tools/aconfig/src/storage/package_table.rs b/tools/aconfig/src/storage/package_table.rs
index 940c5b2..1a3bbc3 100644
--- a/tools/aconfig/src/storage/package_table.rs
+++ b/tools/aconfig/src/storage/package_table.rs
@@ -249,7 +249,7 @@
let first_node_expected = PackageTableNode {
package_name: String::from("com.android.aconfig.storage.test_2"),
package_id: 1,
- boolean_offset: 10,
+ boolean_offset: 6,
next_offset: None,
bucket_index: 0,
};
@@ -265,7 +265,7 @@
let third_node_expected = PackageTableNode {
package_name: String::from("com.android.aconfig.storage.test_4"),
package_id: 2,
- boolean_offset: 16,
+ boolean_offset: 12,
next_offset: None,
bucket_index: 3,
};
diff --git a/tools/aconfig/tests/storage_test_1_part_1.aconfig b/tools/aconfig/tests/storage_test_1.aconfig
similarity index 72%
rename from tools/aconfig/tests/storage_test_1_part_1.aconfig
rename to tools/aconfig/tests/storage_test_1.aconfig
index 70462cd..a122c57 100644
--- a/tools/aconfig/tests/storage_test_1_part_1.aconfig
+++ b/tools/aconfig/tests/storage_test_1.aconfig
@@ -15,3 +15,10 @@
bug: "456"
is_exported: true
}
+
+flag {
+ name: "enabled_ro"
+ namespace: "aconfig_test"
+ description: "This flag is ENABLED + READ_ONLY"
+ bug: "abc"
+}
diff --git a/tools/aconfig/tests/storage_test_1_part_2.aconfig b/tools/aconfig/tests/storage_test_1_part_2.aconfig
deleted file mode 100644
index 5eb0c0c..0000000
--- a/tools/aconfig/tests/storage_test_1_part_2.aconfig
+++ /dev/null
@@ -1,24 +0,0 @@
-package: "com.android.aconfig.storage.test_1"
-container: "system"
-
-flag {
- name: "enabled_ro"
- namespace: "aconfig_test"
- description: "This flag is ENABLED + READ_ONLY"
- bug: "abc"
-}
-
-flag {
- name: "disabled_ro"
- namespace: "aconfig_test"
- description: "This flag is DISABLED + READ_ONLY"
- bug: "123"
-}
-
-flag {
- name: "enabled_fixed_ro"
- namespace: "aconfig_test"
- description: "This flag is fixed READ_ONLY + ENABLED"
- bug: ""
- is_fixed_read_only: true
-}
diff --git a/tools/sbom/generate-sbom-framework_res.py b/tools/sbom/generate-sbom-framework_res.py
index e637d53..d0d232d 100644
--- a/tools/sbom/generate-sbom-framework_res.py
+++ b/tools/sbom/generate-sbom-framework_res.py
@@ -52,8 +52,19 @@
filename = 'data/framework_res.jar'
file_id = f'SPDXRef-{sbom_data.encode_for_spdxid(filename)}'
file = sbom_data.File(id=file_id, name=filename, checksum='SHA1: <checksum>')
+
+ package_name = 'framework_res'
+ package_id = f'SPDXRef-PREBUILT-{sbom_data.encode_for_spdxid(package_name)}'
+ package = sbom_data.Package(id=package_id, name=package_name, version='<package_version>',
+ download_location=sbom_data.VALUE_NONE,
+ supplier='Organization: <organization>',
+ files_analyzed=True,
+ verification_code='<package_verification_code>')
+ package.file_ids.append(file_id)
+
+ doc.packages.append(package)
doc.files.append(file)
- doc.describes = file_id
+ doc.describes = package_id
with open(args.layoutlib_sbom, 'r', encoding='utf-8') as f:
layoutlib_sbom = json.load(f)
@@ -72,7 +83,9 @@
if file[sbom_writers.PropNames.FILE_NAME].startswith('data/res/'):
resource_file_spdxids.append(file[sbom_writers.PropNames.SPDXID])
- doc.relationships = []
+ doc.relationships = [
+ sbom_data.Relationship(package_id, sbom_data.RelationshipType.CONTAINS, file_id)
+ ]
for spdxid in resource_file_spdxids:
doc.relationships.append(
sbom_data.Relationship(file_id, sbom_data.RelationshipType.GENERATED_FROM,