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