xref: /aosp_15_r20/system/server_configurable_flags/aconfigd/storage_files_manager.cpp (revision 207333786ba243bc7d4d69ef6b05487aa7071806)
1 
2 /*
3  * Copyright (C) 2024 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "storage_files_manager.h"
19 
20 #include <android-base/logging.h>
21 
22 #include "aconfigd.h"
23 #include "aconfigd_util.h"
24 #include "com_android_aconfig_new_storage.h"
25 
26 using namespace aconfig_storage;
27 
28 namespace android {
29   namespace aconfigd {
30 
31   /// get storage files object for a container
GetStorageFiles(const std::string & container)32   base::Result<StorageFiles*> StorageFilesManager::GetStorageFiles(
33       const std::string& container) {
34     if (all_storage_files_.count(container) == 0) {
35       return base::Error() << "Missing storage files object for " << container;
36     }
37     return all_storage_files_[container].get();
38   }
39 
40   /// create mapped files for a container
AddNewStorageFiles(const std::string & container,const std::string & package_map,const std::string & flag_map,const std::string & flag_val,const std::string & flag_info)41   base::Result<StorageFiles*> StorageFilesManager::AddNewStorageFiles(
42       const std::string& container,
43       const std::string& package_map,
44       const std::string& flag_map,
45       const std::string& flag_val,
46       const std::string& flag_info) {
47     if (all_storage_files_.count(container)) {
48       return base::Error() << "Storage file object for " << container << " already exists";
49     }
50 
51     auto result = base::Result<void>({});
52     auto storage_files = std::make_unique<StorageFiles>(
53           container, package_map, flag_map, flag_val, flag_info, root_dir_, result);
54 
55     if (!result.ok()) {
56       return base::Error() << "Failed to create storage file object for " << container
57                      << ": " << result.error();
58     }
59 
60     auto storage_files_ptr = storage_files.get();
61     all_storage_files_[container].reset(storage_files.release());
62     return storage_files_ptr;
63   }
64 
65   /// restore storage files object from a storage record pb entry
RestoreStorageFiles(const PersistStorageRecord & pb)66   base::Result<void> StorageFilesManager::RestoreStorageFiles(
67       const PersistStorageRecord& pb) {
68     if (all_storage_files_.count(pb.container())) {
69       return base::Error() << "Storage file object for " << pb.container()
70                      << " already exists";
71     }
72 
73     all_storage_files_[pb.container()] = std::make_unique<StorageFiles>(pb, root_dir_);
74     return {};
75   }
76 
77   /// update existing storage files object with new storage file set
UpdateStorageFiles(const std::string & container,const std::string & package_map,const std::string & flag_map,const std::string & flag_val,const std::string & flag_info)78   base::Result<void> StorageFilesManager::UpdateStorageFiles(
79       const std::string& container,
80       const std::string& package_map,
81       const std::string& flag_map,
82       const std::string& flag_val,
83       const std::string& flag_info) {
84     if (!all_storage_files_.count(container)) {
85       return base::Error() << "Failed to update storage files object for " << container
86                      << ", it does not exist";
87     }
88 
89     // backup server and local override
90     auto storage_files = GetStorageFiles(container);
91     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
92     auto server_overrides = (**storage_files).GetServerFlagValues();
93     RETURN_IF_ERROR(server_overrides, "Failed to get existing server overrides");
94 
95     auto pb_file = (**storage_files).GetStorageRecord().local_overrides;
96     auto local_overrides = ReadPbFromFile<LocalFlagOverrides>(pb_file);
97     RETURN_IF_ERROR(local_overrides, "Failed to read local overrides from " + pb_file);
98 
99     // clean up existing storage files object and recreate
100     (**storage_files).RemoveAllPersistFiles();
101     all_storage_files_.erase(container);
102     storage_files = AddNewStorageFiles(
103         container, package_map, flag_map, flag_val, flag_info);
104     RETURN_IF_ERROR(storage_files, "Failed to add a new storage object for " + container);
105 
106     // reapply local overrides
107     auto updated_local_overrides = LocalFlagOverrides();
108     for (const auto& entry : local_overrides->overrides()) {
109       auto has_flag = (**storage_files).HasFlag(entry.package_name(), entry.flag_name());
110       RETURN_IF_ERROR(has_flag, "Failed to check if has flag for " + entry.package_name()
111                       + "/" + entry.flag_name());
112       if (*has_flag) {
113         auto context = (**storage_files).GetPackageFlagContext(
114             entry.package_name(), entry.flag_name());
115         RETURN_IF_ERROR(context, "Failed to find package flag context for " +
116                         entry.package_name() + "/" + entry.flag_name());
117 
118         auto update = (**storage_files).SetHasLocalOverride(*context, true);
119         RETURN_IF_ERROR(update, "Failed to set flag has local override");
120 
121         auto* new_override = updated_local_overrides.add_overrides();
122         new_override->set_package_name(entry.package_name());
123         new_override->set_flag_name(entry.flag_name());
124         new_override->set_flag_value(entry.flag_value());
125       }
126     }
127     auto result = WritePbToFile<LocalFlagOverrides>(updated_local_overrides, pb_file);
128 
129     // reapply server overrides
130     for (const auto& entry : *server_overrides) {
131       auto has_flag = (**storage_files).HasFlag(entry.package_name, entry.flag_name);
132       RETURN_IF_ERROR(has_flag, "Failed to check if has flag for " + entry.package_name
133                       + "/" + entry.flag_name);
134       if (*has_flag) {
135         auto context = (**storage_files).GetPackageFlagContext(
136             entry.package_name, entry.flag_name);
137         RETURN_IF_ERROR(context, "Failed to find package flag context for " +
138                         entry.package_name + "/" + entry.flag_name);
139 
140         auto update = (**storage_files).SetServerFlagValue(*context, entry.flag_value);
141         RETURN_IF_ERROR(update, "Failed to set server flag value");
142       }
143     }
144 
145     return {};
146   }
147 
148   /// add or update storage file set for a container
AddOrUpdateStorageFiles(const std::string & container,const std::string & package_map,const std::string & flag_map,const std::string & flag_val,const std::string & flag_info)149   base::Result<bool> StorageFilesManager::AddOrUpdateStorageFiles(
150       const std::string& container,
151       const std::string& package_map,
152       const std::string& flag_map,
153       const std::string& flag_val,
154       const std::string& flag_info) {
155     bool new_container = !HasContainer(container);
156     bool update_existing_container = false;
157     if (!new_container) {
158       auto digest = GetFilesDigest({package_map, flag_map, flag_val, flag_info});
159       RETURN_IF_ERROR(digest, "Failed to get digest for " + container);
160       auto storage_files = GetStorageFiles(container);
161       RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
162       if ((**storage_files).GetStorageRecord().digest != *digest) {
163         update_existing_container = true;
164       }
165     }
166 
167     // early return if no update is needed
168     if (!(new_container || update_existing_container)) {
169       return false;
170     }
171 
172     if (new_container) {
173       auto storage_files = AddNewStorageFiles(
174           container, package_map, flag_map, flag_val, flag_info);
175       RETURN_IF_ERROR(storage_files, "Failed to add a new storage object for " + container);
176     } else {
177       auto storage_files = UpdateStorageFiles(
178           container, package_map, flag_map, flag_val, flag_info);
179       RETURN_IF_ERROR(storage_files, "Failed to update storage object for " + container);
180     }
181 
182     return true;
183   }
184 
185   /// create boot copy
CreateStorageBootCopy(const std::string & container)186   base::Result<void> StorageFilesManager::CreateStorageBootCopy(
187       const std::string& container) {
188     if (!HasContainer(container)) {
189       return base::Error() << "Cannot create boot copy without persist copy for " << container;
190     }
191     auto storage_files = GetStorageFiles(container);
192     auto copy_result = (**storage_files).CreateBootStorageFiles();
193     RETURN_IF_ERROR(copy_result, "Failed to create boot copies for " + container);
194     return {};
195   }
196 
197   /// reset all storage
ResetAllStorage()198   base::Result<void> StorageFilesManager::ResetAllStorage() {
199     for (const auto& container : GetAllContainers()) {
200       auto storage_files = GetStorageFiles(container);
201       RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
202       bool available = (**storage_files).HasBootCopy();
203       StorageRecord record = (**storage_files).GetStorageRecord();
204 
205       (**storage_files).RemoveAllPersistFiles();
206       all_storage_files_.erase(container);
207 
208       if (available) {
209         auto storage_files = AddNewStorageFiles(
210             container, record.package_map, record.flag_map, record.flag_val, record.flag_info);
211         RETURN_IF_ERROR(storage_files, "Failed to add a new storage object for " + container);
212       }
213     }
214     return {};
215   }
216 
217   /// get container name given flag package name
GetContainer(const std::string & package)218   base::Result<std::string> StorageFilesManager::GetContainer(
219       const std::string& package) {
220     if (package_to_container_.count(package)) {
221       return package_to_container_[package];
222     }
223 
224     for (const auto& [container, storage_files] : all_storage_files_) {
225       auto has_flag = storage_files->HasPackage(package);
226       RETURN_IF_ERROR(has_flag, "Failed to check if has flag");
227 
228       if (*has_flag) {
229         package_to_container_[package] = container;
230         return container;
231       }
232     }
233 
234     return base::Error() << "container not found";
235   }
236 
237   /// Get all storage records
GetAllStorageRecords()238   std::vector<const StorageRecord*> StorageFilesManager::GetAllStorageRecords() {
239     auto all_records = std::vector<const StorageRecord*>();
240     for (auto const& [container, files_ptr] : all_storage_files_) {
241       all_records.push_back(&(files_ptr->GetStorageRecord()));
242     }
243     return all_records;
244   }
245 
246   /// get all containers
GetAllContainers()247   std::vector<std::string> StorageFilesManager::GetAllContainers() {
248     auto containers = std::vector<std::string>();
249     for (const auto& item : all_storage_files_) {
250       containers.push_back(item.first);
251     }
252     return containers;
253   }
254 
255   /// write to persist storage records pb file
WritePersistStorageRecordsToFile(const std::string & file_name)256   base::Result<void> StorageFilesManager::WritePersistStorageRecordsToFile(
257       const std::string& file_name) {
258     auto records_pb = PersistStorageRecords();
259     for (const auto& [container, storage_files] : all_storage_files_) {
260       const auto& record = storage_files->GetStorageRecord();
261       auto* record_pb = records_pb.add_records();
262       record_pb->set_version(record.version);
263       record_pb->set_container(record.container);
264       record_pb->set_package_map(record.package_map);
265       record_pb->set_flag_map(record.flag_map);
266       record_pb->set_flag_val(record.flag_val);
267       record_pb->set_flag_info(record.flag_info);
268       record_pb->set_digest(record.digest);
269     }
270     return WritePbToFile<PersistStorageRecords>(records_pb, file_name);
271   }
272 
273   /// apply flag override
UpdateFlagValue(const std::string & package_name,const std::string & flag_name,const std::string & flag_value,const StorageRequestMessage::FlagOverrideType override_type)274   base::Result<void> StorageFilesManager::UpdateFlagValue(
275       const std::string& package_name, const std::string& flag_name,
276       const std::string& flag_value,
277       const StorageRequestMessage::FlagOverrideType override_type) {
278     auto container = GetContainer(package_name);
279     RETURN_IF_ERROR(container, "Failed to find owning container");
280 
281     auto storage_files = GetStorageFiles(*container);
282     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
283 
284     auto context = (**storage_files).GetPackageFlagContext(package_name, flag_name);
285     RETURN_IF_ERROR(context, "Failed to find package flag context");
286 
287     switch (override_type) {
288       case StorageRequestMessage::LOCAL_ON_REBOOT: {
289         auto update = (**storage_files).SetLocalFlagValue(*context, flag_value);
290         RETURN_IF_ERROR(update, "Failed to set local flag override");
291         break;
292       }
293       case StorageRequestMessage::SERVER_ON_REBOOT: {
294         auto update =
295             (**storage_files).SetServerFlagValue(*context, flag_value);
296         RETURN_IF_ERROR(update, "Failed to set server flag value");
297         break;
298       }
299       case StorageRequestMessage::LOCAL_IMMEDIATE: {
300         auto updateOverride =
301             (**storage_files).SetLocalFlagValue(*context, flag_value);
302         RETURN_IF_ERROR(updateOverride, "Failed to set local flag override");
303         auto updateBootFile =
304             (**storage_files)
305                 .UpdateBootValueAndInfoImmediately(*context, flag_value, true);
306         RETURN_IF_ERROR(updateBootFile,
307                         "Failed to write local override to boot file");
308         break;
309       }
310       default:
311         return base::Error() << "unknown flag override type";
312     }
313 
314     return {};
315   }
316 
317   /// apply ota flags and return remaining ota flags
ApplyOTAFlagsForContainer(const std::string & container,const std::vector<FlagOverride> & ota_flags)318   base::Result<std::vector<FlagOverride>> StorageFilesManager::ApplyOTAFlagsForContainer(
319       const std::string& container,
320       const std::vector<FlagOverride>& ota_flags) {
321     auto storage_files = GetStorageFiles(container);
322     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
323 
324     auto remaining_ota_flags = std::vector<FlagOverride>();
325     for (const auto& entry : ota_flags) {
326       auto has_flag = (**storage_files).HasPackage(entry.package_name());
327       RETURN_IF_ERROR(has_flag, "Failed to check if has flag");
328       if (*has_flag) {
329         auto result = UpdateFlagValue(entry.package_name(),
330                                       entry.flag_name(),
331                                       entry.flag_value());
332         if (!result.ok()) {
333           LOG(ERROR) << "Failed to apply staged OTA flag " << entry.package_name()
334                      << "/" << entry.flag_name() << ": " << result.error();
335         }
336       } else {
337         remaining_ota_flags.push_back(entry);
338       }
339     }
340 
341     return remaining_ota_flags;
342   }
343 
344   /// remove all local overrides
RemoveAllLocalOverrides(const StorageRequestMessage::RemoveOverrideType remove_override_type)345   base::Result<void> StorageFilesManager::RemoveAllLocalOverrides(
346       const StorageRequestMessage::RemoveOverrideType remove_override_type) {
347     for (const auto& [container, storage_files] : all_storage_files_) {
348       bool immediate =
349           remove_override_type == StorageRequestMessage::REMOVE_LOCAL_IMMEDIATE;
350       auto update = storage_files->RemoveAllLocalFlagValue(immediate);
351       RETURN_IF_ERROR(update, "Failed to remove local overrides for " + container);
352     }
353     return {};
354   }
355 
356   /// remove a local override
RemoveFlagLocalOverride(const std::string & package,const std::string & flag,const StorageRequestMessage::RemoveOverrideType remove_override_type)357   base::Result<void> StorageFilesManager::RemoveFlagLocalOverride(
358       const std::string& package, const std::string& flag,
359       const StorageRequestMessage::RemoveOverrideType remove_override_type) {
360     auto container = GetContainer(package);
361     RETURN_IF_ERROR(container, "Failed to find owning container");
362 
363     auto storage_files = GetStorageFiles(*container);
364     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
365 
366     auto context = (**storage_files).GetPackageFlagContext(package, flag);
367     RETURN_IF_ERROR(context, "Failed to find package flag context");
368 
369     bool immediate =
370         remove_override_type == StorageRequestMessage::REMOVE_LOCAL_IMMEDIATE;
371     auto removed = (**storage_files).RemoveLocalFlagValue(*context, immediate);
372     RETURN_IF_ERROR(removed, "Failed to remove local override");
373 
374     return {};
375   }
376 
377   /// list a flag
ListFlag(const std::string & package,const std::string & flag)378   base::Result<StorageFiles::FlagSnapshot> StorageFilesManager::ListFlag(
379       const std::string& package,
380       const std::string& flag) {
381     auto container = GetContainer(package);
382     RETURN_IF_ERROR(container, "Failed to find owning container");
383     auto storage_files = GetStorageFiles(*container);
384     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
385 
386     if ((**storage_files).HasBootCopy()) {
387       return (**storage_files).ListFlag(package, flag);
388     } else{
389       return base::Error() << "Container " << *container << " is currently unavailable";
390     }
391   }
392 
393   /// list flags in a package
394   base::Result<std::vector<StorageFiles::FlagSnapshot>>
ListFlagsInPackage(const std::string & package)395       StorageFilesManager::ListFlagsInPackage(const std::string& package) {
396     auto container = GetContainer(package);
397     RETURN_IF_ERROR(container, "Failed to find owning container for " + package);
398     auto storage_files = GetStorageFiles(*container);
399     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
400 
401     if ((**storage_files).HasBootCopy()) {
402       return (**storage_files).ListFlags(package);
403     } else{
404       return base::Error() << "Container " << *container << " is currently unavailable";
405     }
406   }
407 
408   /// list flags in a container
409   base::Result<std::vector<StorageFiles::FlagSnapshot>>
ListFlagsInContainer(const std::string & container)410       StorageFilesManager::ListFlagsInContainer(const std::string& container) {
411     auto storage_files = GetStorageFiles(container);
412     RETURN_IF_ERROR(storage_files, "Failed to get storage files object");
413 
414     if ((**storage_files).HasBootCopy()) {
415       return (**storage_files).ListFlags();
416     } else {
417       return base::Error() << "Container " << container << " is currently unavailable";
418     }
419   }
420 
421   /// list all available flags
422   base::Result<std::vector<StorageFiles::FlagSnapshot>>
ListAllAvailableFlags()423       StorageFilesManager::ListAllAvailableFlags() {
424     auto total_flags = std::vector<StorageFiles::FlagSnapshot>();
425     for (const auto& [container, storage_files] : all_storage_files_) {
426       if (!storage_files->HasBootCopy()) {
427         continue;
428       }
429       auto flags = storage_files->ListFlags();
430       RETURN_IF_ERROR(flags, "Failed to list flags in " + container);
431       total_flags.reserve(total_flags.size() + flags->size());
432       total_flags.insert(total_flags.end(), flags->begin(), flags->end());
433     }
434     return total_flags;
435   }
436 
437   } // namespace aconfigd
438 } // namespace android
439