• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use crate::commands::assign_flag_ids;
18 use crate::storage::FlagPackage;
19 use aconfig_protos::{ProtoFlagPermission, ProtoFlagState};
20 use aconfig_storage_file::{FlagValueHeader, FlagValueList, StorageFileType};
21 use anyhow::{anyhow, Result};
22 
new_header(container: &str, num_flags: u32, version: u32) -> FlagValueHeader23 fn new_header(container: &str, num_flags: u32, version: u32) -> FlagValueHeader {
24     FlagValueHeader {
25         version,
26         container: String::from(container),
27         file_type: StorageFileType::FlagVal as u8,
28         file_size: 0,
29         num_flags,
30         boolean_value_offset: 0,
31     }
32 }
33 
create_flag_value( container: &str, packages: &[FlagPackage], version: u32, ) -> Result<FlagValueList>34 pub fn create_flag_value(
35     container: &str,
36     packages: &[FlagPackage],
37     version: u32,
38 ) -> Result<FlagValueList> {
39     // Exclude system/vendor/product flags that are RO+disabled.
40     let mut filtered_packages = packages.to_vec();
41     if container == "system" || container == "vendor" || container == "product" {
42         for package in filtered_packages.iter_mut() {
43             package.boolean_flags.retain(|b| {
44                 !(b.state == Some(ProtoFlagState::DISABLED.into())
45                     && b.permission == Some(ProtoFlagPermission::READ_ONLY.into()))
46             });
47         }
48     }
49     let num_flags = filtered_packages.iter().map(|pkg| pkg.boolean_flags.len() as u32).sum();
50     let mut list = FlagValueList {
51         header: new_header(container, num_flags, version),
52         booleans: vec![false; num_flags as usize],
53     };
54     for pkg in filtered_packages {
55         let start_index = pkg.boolean_start_index as usize;
56         let flag_ids = assign_flag_ids(pkg.package_name, pkg.boolean_flags.iter().copied())?;
57         for pf in pkg.boolean_flags.iter() {
58             let fid = flag_ids
59                 .get(pf.name())
60                 .ok_or(anyhow!(format!("missing flag id for {}", pf.name())))?;
61 
62             list.booleans[start_index + (*fid as usize)] = pf.state() == ProtoFlagState::ENABLED;
63         }
64     }
65 
66     // initialize all header fields
67     list.header.boolean_value_offset = list.header.into_bytes().len() as u32;
68     list.header.file_size = list.header.boolean_value_offset + num_flags;
69 
70     Ok(list)
71 }
72 
73 #[cfg(test)]
74 mod tests {
75     use aconfig_storage_file::DEFAULT_FILE_VERSION;
76 
77     use super::*;
78     use crate::storage::{group_flags_by_package, tests::parse_all_test_flags};
79 
create_test_flag_value_list_from_source() -> Result<FlagValueList>80     pub fn create_test_flag_value_list_from_source() -> Result<FlagValueList> {
81         let caches = parse_all_test_flags();
82         let packages = group_flags_by_package(caches.iter(), DEFAULT_FILE_VERSION);
83         create_flag_value("mockup", &packages, DEFAULT_FILE_VERSION)
84     }
85 
86     #[test]
87     // this test point locks down the flag value creation and each field
test_list_contents()88     fn test_list_contents() {
89         let flag_value_list = create_test_flag_value_list_from_source();
90         assert!(flag_value_list.is_ok());
91         let expected_flag_value_list =
92             aconfig_storage_file::test_utils::create_test_flag_value_list(DEFAULT_FILE_VERSION);
93         assert_eq!(flag_value_list.unwrap(), expected_flag_value_list);
94     }
95 }
96