• 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::storage_files::{FlagSnapshot, StorageFiles};
18 use crate::utils::{get_files_digest, read_pb_from_file, remove_file, write_pb_to_file};
19 use crate::AconfigdError;
20 use aconfigd_protos::{
21     ProtoFlagOverride, ProtoFlagOverrideType, ProtoLocalFlagOverrides, ProtoOTAFlagStagingMessage,
22     ProtoPersistStorageRecord, ProtoPersistStorageRecords, ProtoRemoveOverrideType,
23 };
24 use log::debug;
25 use std::collections::HashMap;
26 use std::path::{Path, PathBuf};
27 
28 // Storage files manager to manage all the storage files across containers
29 #[derive(Debug)]
30 pub(crate) struct StorageFilesManager {
31     pub root_dir: PathBuf,
32     pub all_storage_files: HashMap<String, StorageFiles>,
33     pub package_to_container: HashMap<String, String>,
34 }
35 
36 impl StorageFilesManager {
37     /// Constructor
new(root_dir: &Path) -> Self38     pub(crate) fn new(root_dir: &Path) -> Self {
39         Self {
40             root_dir: root_dir.to_path_buf(),
41             all_storage_files: HashMap::new(),
42             package_to_container: HashMap::new(),
43         }
44     }
45 
46     /// Get storage files for a container
get_storage_files(&mut self, container: &str) -> Option<&mut StorageFiles>47     fn get_storage_files(&mut self, container: &str) -> Option<&mut StorageFiles> {
48         self.all_storage_files.get_mut(container)
49     }
50 
51     /// Add storage files based on a storage record pb entry
add_storage_files_from_pb( &mut self, pb: &ProtoPersistStorageRecord, ) -> Result<(), AconfigdError>52     pub(crate) fn add_storage_files_from_pb(
53         &mut self,
54         pb: &ProtoPersistStorageRecord,
55     ) -> Result<(), AconfigdError> {
56         if self.all_storage_files.contains_key(pb.container()) {
57             debug!(
58                 "Ignored request to add storage files from pb for {}, already exists",
59                 pb.container()
60             );
61             return Ok(());
62         }
63 
64         if aconfig_new_storage_flags::bluetooth_flag_value_bug_fix() {
65             // Only create storage file object if the container is active. This is to
66             // ensure that for inactive containers, the storage files object will not
67             // be created and thus their boot copy will not be produced. And thus we
68             // can prevent them from being used.
69             if PathBuf::from(pb.package_map()).exists()
70                 && PathBuf::from(pb.flag_map()).exists()
71                 && PathBuf::from(pb.flag_val()).exists()
72                 && PathBuf::from(pb.flag_info()).exists()
73             {
74                 self.all_storage_files.insert(
75                     String::from(pb.container()),
76                     StorageFiles::from_pb(pb, &self.root_dir)?,
77                 );
78             }
79         } else {
80             self.all_storage_files
81                 .insert(String::from(pb.container()), StorageFiles::from_pb(pb, &self.root_dir)?);
82         }
83 
84         Ok(())
85     }
86 
87     /// Add a new container's storage files
add_storage_files_from_container( &mut self, container: &str, default_package_map: &Path, default_flag_map: &Path, default_flag_val: &Path, default_flag_info: &Path, ) -> Result<&mut StorageFiles, AconfigdError>88     fn add_storage_files_from_container(
89         &mut self,
90         container: &str,
91         default_package_map: &Path,
92         default_flag_map: &Path,
93         default_flag_val: &Path,
94         default_flag_info: &Path,
95     ) -> Result<&mut StorageFiles, AconfigdError> {
96         if self.all_storage_files.contains_key(container) {
97             debug!(
98                 "Ignored request to add storage files from container {}, already exists",
99                 container
100             );
101         }
102 
103         self.all_storage_files.insert(
104             String::from(container),
105             StorageFiles::from_container(
106                 container,
107                 default_package_map,
108                 default_flag_map,
109                 default_flag_val,
110                 default_flag_info,
111                 &self.root_dir,
112             )?,
113         );
114 
115         self.all_storage_files
116             .get_mut(container)
117             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })
118     }
119 
120     /// Update a container's storage files in the case of container update
update_container_storage_files( &mut self, container: &str, default_package_map: &Path, default_flag_map: &Path, default_flag_val: &Path, default_flag_info: &Path, ) -> Result<(), AconfigdError>121     fn update_container_storage_files(
122         &mut self,
123         container: &str,
124         default_package_map: &Path,
125         default_flag_map: &Path,
126         default_flag_val: &Path,
127         default_flag_info: &Path,
128     ) -> Result<(), AconfigdError> {
129         debug!("update {} storage files", container);
130         let mut storage_files = self
131             .get_storage_files(container)
132             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
133 
134         // backup overrides
135         let server_overrides = storage_files.get_all_server_overrides()?;
136         let local_overrides = storage_files.get_all_local_overrides()?;
137 
138         // recreate storage files object
139         storage_files.remove_persist_files()?;
140         self.all_storage_files.remove(container);
141         storage_files = self.add_storage_files_from_container(
142             container,
143             default_package_map,
144             default_flag_map,
145             default_flag_val,
146             default_flag_info,
147         )?;
148 
149         // restage server overrides
150         debug!("restaging existing server overrides");
151         for f in server_overrides.iter() {
152             let context = storage_files.get_package_flag_context(&f.package_name, &f.flag_name)?;
153             if context.flag_exists {
154                 storage_files.stage_server_override(&context, &f.flag_value)?;
155             }
156         }
157 
158         // restage local overrides
159         debug!("restaging existing local overrides");
160         let mut new_pb = ProtoLocalFlagOverrides::new();
161         for f in local_overrides.into_iter() {
162             let context =
163                 storage_files.get_package_flag_context(f.package_name(), f.flag_name())?;
164             if context.flag_exists {
165                 storage_files.stage_local_override(&context, f.flag_value())?;
166                 new_pb.overrides.push(f);
167             }
168         }
169         write_pb_to_file::<ProtoLocalFlagOverrides>(
170             &new_pb,
171             &storage_files.storage_record.local_overrides,
172         )?;
173 
174         Ok(())
175     }
176 
177     /// add or update a container's storage files in the case of container
178     /// update
add_or_update_container_storage_files( &mut self, container: &str, default_package_map: &Path, default_flag_map: &Path, default_flag_val: &Path, default_flag_info: &Path, ) -> Result<(), AconfigdError>179     pub(crate) fn add_or_update_container_storage_files(
180         &mut self,
181         container: &str,
182         default_package_map: &Path,
183         default_flag_map: &Path,
184         default_flag_val: &Path,
185         default_flag_info: &Path,
186     ) -> Result<(), AconfigdError> {
187         match self.get_storage_files(container) {
188             Some(storage_files) => {
189                 let digest = get_files_digest(
190                     &[default_package_map, default_flag_map, default_flag_val, default_flag_info][..],
191                 )?;
192                 if storage_files.storage_record.digest != digest {
193                     self.update_container_storage_files(
194                         container,
195                         default_package_map,
196                         default_flag_map,
197                         default_flag_val,
198                         default_flag_info,
199                     )?;
200                 } else {
201                     debug!("no need to update {}, computed digest matches with record", container);
202                 }
203             }
204             None => {
205                 self.add_storage_files_from_container(
206                     container,
207                     default_package_map,
208                     default_flag_map,
209                     default_flag_val,
210                     default_flag_info,
211                 )?;
212             }
213         }
214 
215         Ok(())
216     }
217 
218     /// Apply all staged server and local overrides
apply_all_staged_overrides( &mut self, container: &str, ) -> Result<(), AconfigdError>219     pub(crate) fn apply_all_staged_overrides(
220         &mut self,
221         container: &str,
222     ) -> Result<(), AconfigdError> {
223         let storage_files = self
224             .get_storage_files(container)
225             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
226         storage_files.apply_all_staged_overrides()?;
227         Ok(())
228     }
229 
230     /// Reset all storage files
reset_all_storage(&mut self) -> Result<(), AconfigdError>231     pub(crate) fn reset_all_storage(&mut self) -> Result<(), AconfigdError> {
232         debug!("reset storage files of all containers");
233         let all_containers = self.all_storage_files.keys().cloned().collect::<Vec<String>>();
234         for container in all_containers {
235             let storage_files = self
236                 .get_storage_files(&container)
237                 .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
238 
239             let record = storage_files.storage_record.clone();
240             storage_files.remove_persist_files()?;
241             self.all_storage_files.remove(&container);
242 
243             self.add_storage_files_from_container(
244                 &container,
245                 &record.default_package_map,
246                 &record.default_flag_map,
247                 &record.default_flag_val,
248                 &record.default_flag_info,
249             )?;
250         }
251         Ok(())
252     }
253 
254     /// Get container
get_container(&mut self, package: &str) -> Result<Option<String>, AconfigdError>255     fn get_container(&mut self, package: &str) -> Result<Option<String>, AconfigdError> {
256         match self.package_to_container.get(package) {
257             Some(container) => Ok(Some(container.clone())),
258             None => {
259                 for (container, storage_files) in &mut self.all_storage_files {
260                     if storage_files.has_package(package)? {
261                         self.package_to_container.insert(String::from(package), container.clone());
262                         return Ok(Some(container.clone()));
263                     }
264                 }
265                 Ok(None)
266             }
267         }
268     }
269 
270     /// Apply flag override
override_flag_value( &mut self, package: &str, flag: &str, value: &str, override_type: ProtoFlagOverrideType, ) -> Result<(), AconfigdError>271     pub(crate) fn override_flag_value(
272         &mut self,
273         package: &str,
274         flag: &str,
275         value: &str,
276         override_type: ProtoFlagOverrideType,
277     ) -> Result<(), AconfigdError> {
278         let container = self
279             .get_container(package)?
280             .ok_or(AconfigdError::FailToFindContainer { package: package.to_string() })?;
281 
282         let storage_files = self
283             .get_storage_files(&container)
284             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
285 
286         let context = storage_files.get_package_flag_context(package, flag)?;
287         match override_type {
288             ProtoFlagOverrideType::SERVER_ON_REBOOT => {
289                 storage_files.stage_server_override(&context, value)?;
290             }
291             ProtoFlagOverrideType::LOCAL_ON_REBOOT => {
292                 storage_files.stage_local_override(&context, value)?;
293             }
294             ProtoFlagOverrideType::LOCAL_IMMEDIATE => {
295                 storage_files.stage_and_apply_local_override(&context, value)?;
296             }
297         }
298 
299         Ok(())
300     }
301 
302     /// Read staged ota flags
get_ota_flags(&mut self) -> Result<Option<Vec<ProtoFlagOverride>>, AconfigdError>303     fn get_ota_flags(&mut self) -> Result<Option<Vec<ProtoFlagOverride>>, AconfigdError> {
304         let ota_pb_file = self.root_dir.join("flags/ota.pb");
305         if !ota_pb_file.exists() {
306             debug!("no OTA flags staged, skip");
307             return Ok(None);
308         }
309 
310         let ota_flags_pb = read_pb_from_file::<ProtoOTAFlagStagingMessage>(&ota_pb_file)?;
311         if let Some(target_build_id) = ota_flags_pb.build_id {
312             let device_build_id = rustutils::system_properties::read("ro.build.fingerprint")
313                 .map_err(|errmsg| AconfigdError::FailToReadBuildFingerPrint { errmsg })?;
314             if device_build_id == Some(target_build_id.clone()) {
315                 remove_file(&ota_pb_file)?;
316                 Ok(Some(ota_flags_pb.overrides))
317             } else {
318                 debug!(
319                     "fingerprint mismatch between OTA flag staging {}, and device {}",
320                     target_build_id,
321                     device_build_id.unwrap_or(String::from("None")),
322                 );
323                 Ok(None)
324             }
325         } else {
326             debug!("ill formatted OTA staged flags, build fingerprint not set");
327             remove_file(&ota_pb_file)?;
328             return Ok(None);
329         }
330     }
331 
332     /// Apply staged ota flags
apply_staged_ota_flags(&mut self) -> Result<(), AconfigdError>333     pub(crate) fn apply_staged_ota_flags(&mut self) -> Result<(), AconfigdError> {
334         if let Some(flags) = self.get_ota_flags()? {
335             debug!("apply staged OTA flags");
336             for flag in flags.iter() {
337                 if let Err(errmsg) = self.override_flag_value(
338                     flag.package_name(),
339                     flag.flag_name(),
340                     flag.flag_value(),
341                     ProtoFlagOverrideType::SERVER_ON_REBOOT,
342                 ) {
343                     debug!(
344                         "failed to apply ota flag override for {}.{}: {:?}",
345                         flag.package_name(),
346                         flag.flag_name(),
347                         errmsg
348                     );
349                 }
350             }
351         }
352         Ok(())
353     }
354 
355     /// Write persist storage records to file
write_persist_storage_records_to_file( &self, file: &Path, ) -> Result<(), AconfigdError>356     pub(crate) fn write_persist_storage_records_to_file(
357         &self,
358         file: &Path,
359     ) -> Result<(), AconfigdError> {
360         debug!("writing updated storage records {}", file.display().to_string());
361         let mut pb = ProtoPersistStorageRecords::new();
362         pb.records = self
363             .all_storage_files
364             .values()
365             .map(|storage_files| {
366                 let record = &storage_files.storage_record;
367                 let mut entry = ProtoPersistStorageRecord::new();
368                 entry.set_version(record.version);
369                 entry.set_container(record.container.clone());
370                 entry.set_package_map(record.default_package_map.display().to_string());
371                 entry.set_flag_map(record.default_flag_map.display().to_string());
372                 entry.set_flag_val(record.default_flag_val.display().to_string());
373                 entry.set_flag_info(record.default_flag_info.display().to_string());
374                 entry.set_digest(record.digest.clone());
375                 entry
376             })
377             .collect();
378         write_pb_to_file(&pb, file)
379     }
380 
381     /// Remove a single local override
remove_local_override( &mut self, package: &str, flag: &str, remove_override_type: ProtoRemoveOverrideType, ) -> Result<(), AconfigdError>382     pub(crate) fn remove_local_override(
383         &mut self,
384         package: &str,
385         flag: &str,
386         remove_override_type: ProtoRemoveOverrideType,
387     ) -> Result<(), AconfigdError> {
388         let container = self
389             .get_container(package)?
390             .ok_or(AconfigdError::FailToFindContainer { package: package.to_string() })?;
391 
392         let storage_files = self
393             .get_storage_files(&container)
394             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
395 
396         let context = storage_files.get_package_flag_context(package, flag)?;
397         let immediate = remove_override_type == ProtoRemoveOverrideType::REMOVE_LOCAL_IMMEDIATE;
398         storage_files.remove_local_override(&context, immediate)
399     }
400 
401     /// Remove all local overrides
remove_all_local_overrides(&mut self) -> Result<(), AconfigdError>402     pub(crate) fn remove_all_local_overrides(&mut self) -> Result<(), AconfigdError> {
403         debug!("remove all local overrides for all containers");
404         for storage_files in self.all_storage_files.values_mut() {
405             storage_files.remove_all_local_overrides()?;
406         }
407         Ok(())
408     }
409 
410     /// Get flag snapshot
get_flag_snapshot( &mut self, package: &str, flag: &str, ) -> Result<Option<FlagSnapshot>, AconfigdError>411     pub(crate) fn get_flag_snapshot(
412         &mut self,
413         package: &str,
414         flag: &str,
415     ) -> Result<Option<FlagSnapshot>, AconfigdError> {
416         match self.get_container(package)? {
417             Some(container) => {
418                 let storage_files = self.get_storage_files(&container).ok_or(
419                     AconfigdError::FailToGetStorageFiles { container: container.to_string() },
420                 )?;
421 
422                 storage_files.get_flag_snapshot(package, flag)
423             }
424             None => Ok(None),
425         }
426     }
427 
428     /// List all flags in a package
list_flags_in_package( &mut self, package: &str, ) -> Result<Vec<FlagSnapshot>, AconfigdError>429     pub(crate) fn list_flags_in_package(
430         &mut self,
431         package: &str,
432     ) -> Result<Vec<FlagSnapshot>, AconfigdError> {
433         let container = self
434             .get_container(package)?
435             .ok_or(AconfigdError::FailToFindContainer { package: package.to_string() })?;
436 
437         let storage_files = self
438             .get_storage_files(&container)
439             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
440 
441         storage_files.list_flags_in_package(package)
442     }
443 
444     /// List flags in a container
list_flags_in_container( &mut self, container: &str, ) -> Result<Vec<FlagSnapshot>, AconfigdError>445     pub(crate) fn list_flags_in_container(
446         &mut self,
447         container: &str,
448     ) -> Result<Vec<FlagSnapshot>, AconfigdError> {
449         let storage_files = self
450             .get_storage_files(&container)
451             .ok_or(AconfigdError::FailToGetStorageFiles { container: container.to_string() })?;
452 
453         storage_files.list_all_flags()
454     }
455 
456     /// List all the flags
list_all_flags(&mut self) -> Result<Vec<FlagSnapshot>, AconfigdError>457     pub(crate) fn list_all_flags(&mut self) -> Result<Vec<FlagSnapshot>, AconfigdError> {
458         debug!("list all flags across containers");
459         let mut flags = Vec::new();
460         for storage_files in self.all_storage_files.values_mut() {
461             match storage_files.list_all_flags() {
462                 Ok(f) => {
463                     flags.extend(f);
464                 }
465                 Err(errmsg) => {
466                     debug!(
467                         "failed to list all flags for {}: {:?}",
468                         storage_files.storage_record.container, errmsg
469                     );
470                 }
471             }
472         }
473         Ok(flags)
474     }
475 }
476 
477 #[cfg(test)]
478 mod tests {
479     use super::*;
480     use crate::storage_files::StorageRecord;
481     use crate::test_utils::{has_same_content, ContainerMock, StorageRootDirMock};
482     use crate::utils::{copy_file, get_files_digest, read_pb_from_file};
483     use aconfig_storage_file::{FlagValueSummary, StoredFlagType};
484     use aconfigd_protos::ProtoFlagOverride;
485 
486     #[test]
test_add_storage_files_from_pb()487     fn test_add_storage_files_from_pb() {
488         let root_dir = StorageRootDirMock::new();
489         let container = ContainerMock::new();
490 
491         let persist_package_map = root_dir.maps_dir.join("mockup.package.map");
492         let persist_flag_map = root_dir.maps_dir.join("mockup.flag.map");
493         let persist_flag_val = root_dir.flags_dir.join("mockup.val");
494         let persist_flag_info = root_dir.flags_dir.join("mockup.info");
495         copy_file(&container.package_map, &persist_package_map, 0o444).unwrap();
496         copy_file(&container.flag_map, &persist_flag_map, 0o444).unwrap();
497         copy_file(&container.flag_val, &persist_flag_val, 0o644).unwrap();
498         copy_file(&container.flag_info, &persist_flag_info, 0o644).unwrap();
499 
500         let mut pb = ProtoPersistStorageRecord::new();
501         pb.set_version(123);
502         pb.set_container("mockup".to_string());
503         pb.set_package_map(container.package_map.display().to_string());
504         pb.set_flag_map(container.flag_map.display().to_string());
505         pb.set_flag_val(container.flag_val.display().to_string());
506         pb.set_flag_info(container.flag_info.display().to_string());
507         pb.set_digest(String::from("abc"));
508 
509         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
510         manager.add_storage_files_from_pb(&pb);
511         assert_eq!(manager.all_storage_files.len(), 1);
512         assert_eq!(
513             manager.all_storage_files.get("mockup").unwrap(),
514             &StorageFiles::from_pb(&pb, &root_dir.tmp_dir.path()).unwrap(),
515         );
516 
517         // Ensure we can run this again, to exercise the case where the storage
518         // files already exist, for example if the storage proto is deleted.
519         manager.add_storage_files_from_pb(&pb);
520         assert_eq!(manager.all_storage_files.len(), 1);
521         assert_eq!(
522             manager.all_storage_files.get("mockup").unwrap(),
523             &StorageFiles::from_pb(&pb, &root_dir.tmp_dir.path()).unwrap(),
524         );
525     }
526 
init_storage(container: &ContainerMock, manager: &mut StorageFilesManager)527     fn init_storage(container: &ContainerMock, manager: &mut StorageFilesManager) {
528         manager
529             .add_or_update_container_storage_files(
530                 &container.name,
531                 &container.package_map,
532                 &container.flag_map,
533                 &container.flag_val,
534                 &container.flag_info,
535             )
536             .unwrap();
537     }
538 
539     #[test]
test_add_storage_files_from_container()540     fn test_add_storage_files_from_container() {
541         let container = ContainerMock::new();
542         let root_dir = StorageRootDirMock::new();
543         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
544         init_storage(&container, &mut manager);
545 
546         let storage_files = manager.get_storage_files(&container.name).unwrap();
547 
548         let expected_record = StorageRecord {
549             version: 1,
550             container: String::from("mockup"),
551             default_package_map: container.package_map.clone(),
552             default_flag_map: container.flag_map.clone(),
553             default_flag_val: container.flag_val.clone(),
554             default_flag_info: container.flag_info.clone(),
555             persist_package_map: root_dir.maps_dir.join("mockup.package.map"),
556             persist_flag_map: root_dir.maps_dir.join("mockup.flag.map"),
557             persist_flag_val: root_dir.flags_dir.join("mockup.val"),
558             persist_flag_info: root_dir.flags_dir.join("mockup.info"),
559             local_overrides: root_dir.flags_dir.join("mockup_local_overrides.pb"),
560             boot_flag_val: root_dir.boot_dir.join("mockup.val"),
561             boot_flag_info: root_dir.boot_dir.join("mockup.info"),
562             digest: get_files_digest(
563                 &[
564                     container.package_map.as_path(),
565                     container.flag_map.as_path(),
566                     container.flag_val.as_path(),
567                     container.flag_info.as_path(),
568                 ][..],
569             )
570             .unwrap(),
571         };
572 
573         let expected_storage_files = StorageFiles {
574             storage_record: expected_record,
575             package_map: None,
576             flag_map: None,
577             flag_val: None,
578             boot_flag_val: None,
579             boot_flag_info: None,
580             persist_flag_val: None,
581             persist_flag_info: None,
582             mutable_boot_flag_val: None,
583             mutable_boot_flag_info: None,
584         };
585 
586         assert_eq!(storage_files, &expected_storage_files);
587 
588         assert!(has_same_content(
589             &container.package_map,
590             &storage_files.storage_record.persist_package_map
591         ));
592         assert!(has_same_content(
593             &container.flag_map,
594             &storage_files.storage_record.persist_flag_map
595         ));
596         assert!(has_same_content(
597             &container.flag_val,
598             &storage_files.storage_record.persist_flag_val
599         ));
600         assert!(has_same_content(
601             &container.flag_info,
602             &storage_files.storage_record.persist_flag_info
603         ));
604         assert!(has_same_content(&container.flag_val, &storage_files.storage_record.boot_flag_val));
605         assert!(has_same_content(
606             &container.flag_info,
607             &storage_files.storage_record.boot_flag_info
608         ));
609     }
610 
611     #[test]
test_simple_update_container_storage_files()612     fn test_simple_update_container_storage_files() {
613         let container = ContainerMock::new();
614         let root_dir = StorageRootDirMock::new();
615         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
616         init_storage(&container, &mut manager);
617 
618         // copy files over to mimic a container update
619         std::fs::copy("./tests/data/container_with_more_flags.package.map", &container.package_map)
620             .unwrap();
621         std::fs::copy("./tests/data/container_with_more_flags.flag.map", &container.flag_map)
622             .unwrap();
623         std::fs::copy("./tests/data/container_with_more_flags.flag.val", &container.flag_val)
624             .unwrap();
625         std::fs::copy("./tests/data/container_with_more_flags.flag.info", &container.flag_info)
626             .unwrap();
627 
628         // update container
629         manager
630             .add_or_update_container_storage_files(
631                 &container.name,
632                 &container.package_map,
633                 &container.flag_map,
634                 &container.flag_val,
635                 &container.flag_info,
636             )
637             .unwrap();
638 
639         let storage_files = manager.get_storage_files(&container.name).unwrap();
640 
641         assert!(has_same_content(
642             &Path::new("./tests/data/container_with_more_flags.package.map"),
643             &storage_files.storage_record.persist_package_map
644         ));
645         assert!(has_same_content(
646             &Path::new("./tests/data/container_with_more_flags.flag.map"),
647             &storage_files.storage_record.persist_flag_map
648         ));
649         assert!(has_same_content(
650             &Path::new("./tests/data/container_with_more_flags.flag.val"),
651             &storage_files.storage_record.persist_flag_val
652         ));
653         assert!(has_same_content(
654             &Path::new("./tests/data/container_with_more_flags.flag.info"),
655             &storage_files.storage_record.persist_flag_info
656         ));
657         assert!(has_same_content(
658             &Path::new("./tests/data/container_with_more_flags.flag.val"),
659             &storage_files.storage_record.boot_flag_val
660         ));
661         assert!(has_same_content(
662             &Path::new("./tests/data/container_with_more_flags.flag.info"),
663             &storage_files.storage_record.boot_flag_info
664         ));
665         assert!(storage_files.storage_record.local_overrides.exists());
666     }
667 
add_example_overrides(manager: &mut StorageFilesManager)668     fn add_example_overrides(manager: &mut StorageFilesManager) {
669         manager
670             .override_flag_value(
671                 "com.android.aconfig.storage.test_1",
672                 "enabled_rw",
673                 "false",
674                 ProtoFlagOverrideType::SERVER_ON_REBOOT,
675             )
676             .unwrap();
677 
678         manager
679             .override_flag_value(
680                 "com.android.aconfig.storage.test_1",
681                 "disabled_rw",
682                 "false",
683                 ProtoFlagOverrideType::SERVER_ON_REBOOT,
684             )
685             .unwrap();
686 
687         manager
688             .override_flag_value(
689                 "com.android.aconfig.storage.test_1",
690                 "disabled_rw",
691                 "true",
692                 ProtoFlagOverrideType::LOCAL_ON_REBOOT,
693             )
694             .unwrap();
695     }
696 
697     #[test]
test_overrides_after_update_container_storage_files()698     fn test_overrides_after_update_container_storage_files() {
699         let container = ContainerMock::new();
700         let root_dir = StorageRootDirMock::new();
701         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
702         init_storage(&container, &mut manager);
703         add_example_overrides(&mut manager);
704 
705         // copy files over to mimic a container update
706         std::fs::copy("./tests/data/package.map", &container.package_map).unwrap();
707         std::fs::copy("./tests/data/flag.map", &container.flag_map).unwrap();
708         std::fs::copy("./tests/data/flag.val", &container.flag_val).unwrap();
709         std::fs::copy("./tests/data/flag.info", &container.flag_info).unwrap();
710 
711         // update container
712         manager
713             .add_or_update_container_storage_files(
714                 &container.name,
715                 &container.package_map,
716                 &container.flag_map,
717                 &container.flag_val,
718                 &container.flag_info,
719             )
720             .unwrap();
721 
722         // verify that server override is persisted
723         let storage_files = manager.get_storage_files(&container.name).unwrap();
724         let server_overrides = storage_files.get_all_server_overrides().unwrap();
725         assert_eq!(server_overrides.len(), 2);
726         assert_eq!(
727             server_overrides[0],
728             FlagValueSummary {
729                 package_name: "com.android.aconfig.storage.test_1".to_string(),
730                 flag_name: "disabled_rw".to_string(),
731                 flag_value: "false".to_string(),
732                 value_type: StoredFlagType::ReadWriteBoolean,
733             }
734         );
735         assert_eq!(
736             server_overrides[1],
737             FlagValueSummary {
738                 package_name: "com.android.aconfig.storage.test_1".to_string(),
739                 flag_name: "enabled_rw".to_string(),
740                 flag_value: "false".to_string(),
741                 value_type: StoredFlagType::ReadWriteBoolean,
742             }
743         );
744 
745         // verify that local override is persisted
746         let local_overrides = storage_files.get_all_local_overrides().unwrap();
747         assert_eq!(local_overrides.len(), 1);
748         let mut pb = ProtoFlagOverride::new();
749         pb.set_package_name("com.android.aconfig.storage.test_1".to_string());
750         pb.set_flag_name("disabled_rw".to_string());
751         pb.set_flag_value("true".to_string());
752         assert_eq!(local_overrides[0], pb);
753     }
754 
755     #[test]
test_apply_all_staged_overrides()756     fn test_apply_all_staged_overrides() {
757         let container = ContainerMock::new();
758         let root_dir = StorageRootDirMock::new();
759         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
760         init_storage(&container, &mut manager);
761         add_example_overrides(&mut manager);
762         manager.apply_all_staged_overrides("mockup").unwrap();
763 
764         let mut flag =
765             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "enabled_rw").unwrap();
766 
767         let mut expected_flag = FlagSnapshot {
768             container: String::from("mockup"),
769             package: String::from("com.android.aconfig.storage.test_1"),
770             flag: String::from("enabled_rw"),
771             server_value: String::from("false"),
772             local_value: String::new(),
773             boot_value: String::from("false"),
774             default_value: String::from("true"),
775             is_readwrite: true,
776             has_server_override: true,
777             has_local_override: false,
778             has_boot_local_override: false,
779         };
780 
781         assert_eq!(flag, Some(expected_flag));
782 
783         flag =
784             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "disabled_rw").unwrap();
785 
786         expected_flag = FlagSnapshot {
787             container: String::from("mockup"),
788             package: String::from("com.android.aconfig.storage.test_1"),
789             flag: String::from("disabled_rw"),
790             server_value: String::from("false"),
791             local_value: String::from("true"),
792             boot_value: String::from("true"),
793             default_value: String::from("false"),
794             is_readwrite: true,
795             has_server_override: true,
796             has_local_override: true,
797             has_boot_local_override: false,
798         };
799 
800         assert_eq!(flag, Some(expected_flag));
801     }
802 
803     #[test]
test_reset_all_storage()804     fn test_reset_all_storage() {
805         let container = ContainerMock::new();
806         let root_dir = StorageRootDirMock::new();
807         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
808         init_storage(&container, &mut manager);
809         add_example_overrides(&mut manager);
810         manager.apply_all_staged_overrides("mockup").unwrap();
811 
812         manager.reset_all_storage().unwrap();
813         let storage_files = manager.get_storage_files(&container.name).unwrap();
814         assert!(has_same_content(
815             &container.flag_val,
816             &storage_files.storage_record.persist_flag_val
817         ));
818         assert!(has_same_content(
819             &container.flag_info,
820             &storage_files.storage_record.persist_flag_info
821         ));
822         assert!(has_same_content(&container.flag_val, &storage_files.storage_record.boot_flag_val));
823         assert!(has_same_content(
824             &container.flag_info,
825             &storage_files.storage_record.boot_flag_info
826         ));
827     }
828 
test_override_flag_server_on_reboot()829     fn test_override_flag_server_on_reboot() {
830         let container = ContainerMock::new();
831         let root_dir = StorageRootDirMock::new();
832         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
833         init_storage(&container, &mut manager);
834         manager.apply_all_staged_overrides("mockup").unwrap();
835 
836         manager
837             .override_flag_value(
838                 "com.android.aconfig.storage.test_1",
839                 "enabled_rw",
840                 "false",
841                 ProtoFlagOverrideType::SERVER_ON_REBOOT,
842             )
843             .unwrap();
844 
845         let flag =
846             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "enabled_rw").unwrap();
847 
848         let expected_flag = FlagSnapshot {
849             container: String::from("mockup"),
850             package: String::from("com.android.aconfig.storage.test_1"),
851             flag: String::from("enabled_rw"),
852             server_value: String::from("false"),
853             local_value: String::new(),
854             boot_value: String::from("true"),
855             default_value: String::from("true"),
856             is_readwrite: true,
857             has_server_override: true,
858             has_local_override: false,
859             has_boot_local_override: false,
860         };
861 
862         assert_eq!(flag, Some(expected_flag));
863     }
864 
865     #[test]
test_override_flag_local_on_reboot()866     fn test_override_flag_local_on_reboot() {
867         let container = ContainerMock::new();
868         let root_dir = StorageRootDirMock::new();
869         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
870         init_storage(&container, &mut manager);
871         manager.apply_all_staged_overrides("mockup").unwrap();
872 
873         manager
874             .override_flag_value(
875                 "com.android.aconfig.storage.test_1",
876                 "enabled_rw",
877                 "false",
878                 ProtoFlagOverrideType::LOCAL_ON_REBOOT,
879             )
880             .unwrap();
881 
882         let flag =
883             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "enabled_rw").unwrap();
884 
885         let expected_flag = FlagSnapshot {
886             container: String::from("mockup"),
887             package: String::from("com.android.aconfig.storage.test_1"),
888             flag: String::from("enabled_rw"),
889             server_value: String::new(),
890             local_value: String::from("false"),
891             boot_value: String::from("true"),
892             default_value: String::from("true"),
893             is_readwrite: true,
894             has_server_override: false,
895             has_local_override: true,
896             has_boot_local_override: false,
897         };
898 
899         assert_eq!(flag, Some(expected_flag));
900     }
901 
902     #[test]
test_override_flag_local_immediate()903     fn test_override_flag_local_immediate() {
904         let container = ContainerMock::new();
905         let root_dir = StorageRootDirMock::new();
906         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
907         init_storage(&container, &mut manager);
908         manager.apply_all_staged_overrides("mockup").unwrap();
909 
910         manager
911             .override_flag_value(
912                 "com.android.aconfig.storage.test_1",
913                 "enabled_rw",
914                 "false",
915                 ProtoFlagOverrideType::LOCAL_IMMEDIATE,
916             )
917             .unwrap();
918 
919         let flag =
920             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "enabled_rw").unwrap();
921 
922         let expected_flag = FlagSnapshot {
923             container: String::from("mockup"),
924             package: String::from("com.android.aconfig.storage.test_1"),
925             flag: String::from("enabled_rw"),
926             server_value: String::new(),
927             local_value: String::from("false"),
928             boot_value: String::from("false"),
929             default_value: String::from("true"),
930             is_readwrite: true,
931             has_server_override: false,
932             has_local_override: true,
933             has_boot_local_override: false,
934         };
935 
936         assert_eq!(flag, Some(expected_flag));
937     }
938 
939     #[test]
test_get_ota_flags()940     fn test_get_ota_flags() {
941         let root_dir = StorageRootDirMock::new();
942         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
943 
944         let mut ota_flags = ProtoOTAFlagStagingMessage::new();
945         ota_flags.set_build_id("xyz.123".to_string());
946         write_pb_to_file::<ProtoOTAFlagStagingMessage>(
947             &ota_flags,
948             &root_dir.flags_dir.join("ota.pb"),
949         )
950         .unwrap();
951         let staged_ota_flags = manager.get_ota_flags().unwrap();
952         assert!(staged_ota_flags.is_none());
953         assert!(root_dir.flags_dir.join("ota.pb").exists());
954 
955         let device_build_id =
956             rustutils::system_properties::read("ro.build.fingerprint").unwrap().unwrap();
957         ota_flags.set_build_id(device_build_id);
958         let mut flag1 = ProtoFlagOverride::new();
959         flag1.set_package_name("com.android.aconfig.storage.test_1".to_string());
960         flag1.set_flag_name("enabled_rw".to_string());
961         flag1.set_flag_value("false".to_string());
962         ota_flags.overrides.push(flag1.clone());
963         let mut flag2 = ProtoFlagOverride::new();
964         flag2.set_package_name("com.android.aconfig.storage.test_2".to_string());
965         flag2.set_flag_name("disabled_rw".to_string());
966         flag2.set_flag_value("true".to_string());
967         ota_flags.overrides.push(flag2.clone());
968         write_pb_to_file::<ProtoOTAFlagStagingMessage>(
969             &ota_flags,
970             &root_dir.flags_dir.join("ota.pb"),
971         )
972         .unwrap();
973         let staged_ota_flags = manager.get_ota_flags().unwrap().unwrap();
974         assert_eq!(staged_ota_flags.len(), 2);
975         assert_eq!(staged_ota_flags[0], flag1);
976         assert_eq!(staged_ota_flags[1], flag2);
977         assert!(!root_dir.flags_dir.join("ota.pb").exists());
978     }
979 
980     #[test]
test_apply_staged_ota_flags()981     fn test_apply_staged_ota_flags() {
982         let container = ContainerMock::new();
983         let root_dir = StorageRootDirMock::new();
984         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
985         init_storage(&container, &mut manager);
986 
987         let mut ota_flags = ProtoOTAFlagStagingMessage::new();
988         let device_build_id =
989             rustutils::system_properties::read("ro.build.fingerprint").unwrap().unwrap();
990         ota_flags.set_build_id(device_build_id);
991         let mut flag1 = ProtoFlagOverride::new();
992         flag1.set_package_name("com.android.aconfig.storage.test_1".to_string());
993         flag1.set_flag_name("enabled_rw".to_string());
994         flag1.set_flag_value("false".to_string());
995         ota_flags.overrides.push(flag1.clone());
996         let mut flag2 = ProtoFlagOverride::new();
997         flag2.set_package_name("com.android.aconfig.storage.test_2".to_string());
998         flag2.set_flag_name("disabled_rw".to_string());
999         flag2.set_flag_value("true".to_string());
1000         ota_flags.overrides.push(flag2.clone());
1001         let mut flag3 = ProtoFlagOverride::new();
1002         flag3.set_package_name("not_exist".to_string());
1003         flag3.set_flag_name("not_exist".to_string());
1004         flag3.set_flag_value("true".to_string());
1005         ota_flags.overrides.push(flag3.clone());
1006         write_pb_to_file::<ProtoOTAFlagStagingMessage>(
1007             &ota_flags,
1008             &root_dir.flags_dir.join("ota.pb"),
1009         )
1010         .unwrap();
1011 
1012         manager.apply_staged_ota_flags().unwrap();
1013         let storage_files = manager.get_storage_files(&container.name).unwrap();
1014         let server_overrides = storage_files.get_all_server_overrides().unwrap();
1015         assert_eq!(server_overrides.len(), 2);
1016         assert_eq!(
1017             server_overrides[0].package_name,
1018             "com.android.aconfig.storage.test_1".to_string()
1019         );
1020         assert_eq!(server_overrides[0].flag_name, "enabled_rw".to_string());
1021         assert_eq!(server_overrides[0].flag_value, "false".to_string());
1022         assert_eq!(
1023             server_overrides[1].package_name,
1024             "com.android.aconfig.storage.test_2".to_string()
1025         );
1026         assert_eq!(server_overrides[1].flag_name, "disabled_rw".to_string());
1027         assert_eq!(server_overrides[1].flag_value, "true".to_string());
1028     }
1029 
1030     #[test]
test_write_persist_storage_records_to_file()1031     fn test_write_persist_storage_records_to_file() {
1032         let container = ContainerMock::new();
1033         let root_dir = StorageRootDirMock::new();
1034         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
1035         init_storage(&container, &mut manager);
1036 
1037         let pb_file = root_dir.tmp_dir.path().join("records.pb");
1038         manager.write_persist_storage_records_to_file(&pb_file).unwrap();
1039 
1040         let pb = read_pb_from_file::<ProtoPersistStorageRecords>(&pb_file).unwrap();
1041         assert_eq!(pb.records.len(), 1);
1042 
1043         let mut entry = ProtoPersistStorageRecord::new();
1044         entry.set_version(1);
1045         entry.set_container("mockup".to_string());
1046         entry.set_package_map(container.package_map.display().to_string());
1047         entry.set_flag_map(container.flag_map.display().to_string());
1048         entry.set_flag_val(container.flag_val.display().to_string());
1049         entry.set_flag_info(container.flag_info.display().to_string());
1050         let digest = get_files_digest(
1051             &[
1052                 container.package_map.as_path(),
1053                 container.flag_map.as_path(),
1054                 container.flag_val.as_path(),
1055                 container.flag_info.as_path(),
1056             ][..],
1057         )
1058         .unwrap();
1059         entry.set_digest(digest);
1060         assert_eq!(pb.records[0], entry);
1061     }
1062 
1063     #[test]
test_remove_local_override()1064     fn test_remove_local_override() {
1065         let container = ContainerMock::new();
1066         let root_dir = StorageRootDirMock::new();
1067         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
1068         init_storage(&container, &mut manager);
1069         add_example_overrides(&mut manager);
1070         manager.apply_all_staged_overrides("mockup").unwrap();
1071 
1072         manager
1073             .remove_local_override(
1074                 "com.android.aconfig.storage.test_1",
1075                 "disabled_rw",
1076                 ProtoRemoveOverrideType::REMOVE_LOCAL_ON_REBOOT,
1077             )
1078             .unwrap();
1079 
1080         let flag =
1081             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "disabled_rw").unwrap();
1082 
1083         let expected_flag = FlagSnapshot {
1084             container: String::from("mockup"),
1085             package: String::from("com.android.aconfig.storage.test_1"),
1086             flag: String::from("disabled_rw"),
1087             server_value: String::from("false"),
1088             local_value: String::new(),
1089             boot_value: String::from("true"),
1090             default_value: String::from("false"),
1091             is_readwrite: true,
1092             has_server_override: true,
1093             has_local_override: false,
1094             has_boot_local_override: false,
1095         };
1096 
1097         assert_eq!(flag, Some(expected_flag));
1098     }
1099 
1100     #[test]
test_remove_all_local_override()1101     fn test_remove_all_local_override() {
1102         let container = ContainerMock::new();
1103         let root_dir = StorageRootDirMock::new();
1104         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
1105         init_storage(&container, &mut manager);
1106 
1107         manager
1108             .override_flag_value(
1109                 "com.android.aconfig.storage.test_1",
1110                 "disabled_rw",
1111                 "true",
1112                 ProtoFlagOverrideType::LOCAL_ON_REBOOT,
1113             )
1114             .unwrap();
1115 
1116         manager
1117             .override_flag_value(
1118                 "com.android.aconfig.storage.test_2",
1119                 "disabled_rw",
1120                 "true",
1121                 ProtoFlagOverrideType::LOCAL_ON_REBOOT,
1122             )
1123             .unwrap();
1124         manager.apply_all_staged_overrides("mockup").unwrap();
1125         manager.remove_all_local_overrides().unwrap();
1126 
1127         let mut flag =
1128             manager.get_flag_snapshot("com.android.aconfig.storage.test_1", "disabled_rw").unwrap();
1129 
1130         let mut expected_flag = FlagSnapshot {
1131             container: String::from("mockup"),
1132             package: String::from("com.android.aconfig.storage.test_1"),
1133             flag: String::from("disabled_rw"),
1134             server_value: String::from(""),
1135             local_value: String::new(),
1136             boot_value: String::from("true"),
1137             default_value: String::from("false"),
1138             is_readwrite: true,
1139             has_server_override: false,
1140             has_local_override: false,
1141             has_boot_local_override: false,
1142         };
1143 
1144         assert_eq!(flag, Some(expected_flag));
1145 
1146         flag =
1147             manager.get_flag_snapshot("com.android.aconfig.storage.test_2", "disabled_rw").unwrap();
1148 
1149         expected_flag = FlagSnapshot {
1150             container: String::from("mockup"),
1151             package: String::from("com.android.aconfig.storage.test_2"),
1152             flag: String::from("disabled_rw"),
1153             server_value: String::from(""),
1154             local_value: String::new(),
1155             boot_value: String::from("true"),
1156             default_value: String::from("false"),
1157             is_readwrite: true,
1158             has_server_override: false,
1159             has_local_override: false,
1160             has_boot_local_override: false,
1161         };
1162 
1163         assert_eq!(flag, Some(expected_flag));
1164     }
1165 
1166     #[test]
test_list_flags_in_package()1167     fn test_list_flags_in_package() {
1168         let container = ContainerMock::new();
1169         let root_dir = StorageRootDirMock::new();
1170         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
1171         init_storage(&container, &mut manager);
1172         add_example_overrides(&mut manager);
1173         manager.apply_all_staged_overrides("mockup").unwrap();
1174 
1175         let flags = manager.list_flags_in_package("com.android.aconfig.storage.test_1").unwrap();
1176 
1177         let mut flag = FlagSnapshot {
1178             container: String::from("mockup"),
1179             package: String::from("com.android.aconfig.storage.test_1"),
1180             flag: String::from("disabled_rw"),
1181             server_value: String::from("false"),
1182             local_value: String::from("true"),
1183             boot_value: String::from("true"),
1184             default_value: String::from("false"),
1185             is_readwrite: true,
1186             has_server_override: true,
1187             has_local_override: true,
1188             has_boot_local_override: false,
1189         };
1190         assert_eq!(flags[0], flag);
1191 
1192         flag = FlagSnapshot {
1193             container: String::from("mockup"),
1194             package: String::from("com.android.aconfig.storage.test_1"),
1195             flag: String::from("enabled_ro"),
1196             server_value: String::new(),
1197             local_value: String::new(),
1198             boot_value: String::from("true"),
1199             default_value: String::from("true"),
1200             is_readwrite: false,
1201             has_server_override: false,
1202             has_local_override: false,
1203             has_boot_local_override: false,
1204         };
1205         assert_eq!(flags[1], flag);
1206 
1207         flag = FlagSnapshot {
1208             container: String::from("mockup"),
1209             package: String::from("com.android.aconfig.storage.test_1"),
1210             flag: String::from("enabled_rw"),
1211             server_value: String::from("false"),
1212             local_value: String::new(),
1213             boot_value: String::from("false"),
1214             default_value: String::from("true"),
1215             is_readwrite: true,
1216             has_server_override: true,
1217             has_local_override: false,
1218             has_boot_local_override: false,
1219         };
1220         assert_eq!(flags[2], flag);
1221     }
1222 
1223     #[test]
test_list_flags_in_container()1224     fn test_list_flags_in_container() {
1225         let container = ContainerMock::new();
1226         let root_dir = StorageRootDirMock::new();
1227         let mut manager = StorageFilesManager::new(&root_dir.tmp_dir.path());
1228         init_storage(&container, &mut manager);
1229         add_example_overrides(&mut manager);
1230         manager.apply_all_staged_overrides("mockup").unwrap();
1231 
1232         let flags = manager.list_flags_in_container("mockup").unwrap();
1233         assert_eq!(flags.len(), 8);
1234 
1235         let mut flag = FlagSnapshot {
1236             container: String::from("mockup"),
1237             package: String::from("com.android.aconfig.storage.test_1"),
1238             flag: String::from("enabled_rw"),
1239             server_value: String::from("false"),
1240             local_value: String::new(),
1241             boot_value: String::from("false"),
1242             default_value: String::from("true"),
1243             is_readwrite: true,
1244             has_server_override: true,
1245             has_local_override: false,
1246             has_boot_local_override: false,
1247         };
1248         assert_eq!(flags[2], flag);
1249 
1250         flag = FlagSnapshot {
1251             container: String::from("mockup"),
1252             package: String::from("com.android.aconfig.storage.test_1"),
1253             flag: String::from("disabled_rw"),
1254             server_value: String::from("false"),
1255             local_value: String::from("true"),
1256             boot_value: String::from("true"),
1257             default_value: String::from("false"),
1258             is_readwrite: true,
1259             has_server_override: true,
1260             has_local_override: true,
1261             has_boot_local_override: false,
1262         };
1263         assert_eq!(flags[0], flag);
1264     }
1265 }
1266