• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "module_update_main.h"
17 
18 #include <fcntl.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <thread>
22 #include <unistd.h>
23 
24 #include "directory_ex.h"
25 #include "module_utils.h"
26 #include "hisysevent_manager.h"
27 #include "json_node.h"
28 #include "log/log.h"
29 #include "module_update_service.h"
30 #include "parameter.h"
31 #include "system_ability_definition.h"
32 #include "module_constants.h"
33 #include "module_update_consumer.h"
34 #include "module_update_producer.h"
35 #include "module_error_code.h"
36 #include "module_file.h"
37 #include "module_update_verify.h"
38 #include "package/package.h"
39 #include "scope_guard.h"
40 #include "utils.h"
41 #include "unique_fd.h"
42 
43 #ifdef WITH_SELINUX
44 #include <policycoreutils.h>
45 #endif // WITH_SELINUX
46 
47 namespace OHOS {
48 namespace SysInstaller {
49 using namespace Updater;
50 
51 namespace {
52 constexpr int32_t RETRY_TIMES_FOR_SAMGR = 10;
53 constexpr std::chrono::milliseconds MILLISECONDS_WAITING_SAMGR_ONE_TIME(100);
54 constexpr mode_t DIR_MODE = 0750;
55 
56 static volatile sig_atomic_t g_exit = 0;
57 
CreateModuleDirs(const std::string & hmpName)58 int32_t CreateModuleDirs(const std::string &hmpName)
59 {
60     if (!CreateDirIfNeeded(UPDATE_INSTALL_DIR, DIR_MODE)) {
61         LOG(ERROR) << "Failed to create install dir";
62         return ModuleErrorCode::ERR_INSTALL_FAIL;
63     }
64 #ifdef WITH_SELINUX
65     if (Restorecon(UPDATE_INSTALL_DIR) == -1) {
66         LOG(WARNING) << "restore " << UPDATE_INSTALL_DIR << " failed";
67     }
68 #endif // WITH_SELINUX
69     std::string hmpInstallDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
70     if (!CreateDirIfNeeded(hmpInstallDir, DIR_MODE)) {
71         LOG(ERROR) << "Failed to create hmp install dir " << hmpInstallDir;
72         return ModuleErrorCode::ERR_INSTALL_FAIL;
73     }
74     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
75 }
76 
GetFileAllName(const std::string & path)77 std::string GetFileAllName(const std::string &path)
78 {
79     auto pos = path.find_last_of('/');
80     if (pos == std::string::npos) {
81         pos = path.find_last_of('\\');
82         if (pos == std::string::npos) {
83             return "";
84         }
85     }
86     return path.substr(pos + 1);
87 }
88 
BackupFile(const std::string & file)89 bool BackupFile(const std::string &file)
90 {
91     std::string fileName = GetFileAllName(file);
92     std::string hmpName = GetHmpName(file);
93     if (fileName.empty() || hmpName.empty()) {
94         return true;
95     }
96     std::string destPath = std::string(UPDATE_BACKUP_DIR) + "/" + hmpName;
97     if (!CreateDirIfNeeded(destPath, DIR_MODE)) {
98         LOG(ERROR) << "Failed to create hmp dir " << destPath;
99         return false;
100     }
101     std::string destFile = destPath + "/" + fileName;
102     int ret = link(file.c_str(), destFile.c_str());
103     if (ret != 0) {
104         LOG(ERROR) << "Failed to link file " << file << " to dest " << destFile;
105         return false;
106     }
107     return true;
108 }
109 }
110 
ModuleUpdateMain()111 ModuleUpdateMain::ModuleUpdateMain()
112 {
113 }
114 
115 ModuleUpdateMain::~ModuleUpdateMain() = default;
116 
CheckHmpName(const std::string & hmpName)117 int32_t ModuleUpdateMain::CheckHmpName(const std::string &hmpName)
118 {
119     if (hmpName.empty()) {
120         LOG(ERROR) << "Failed to get hmpName=" << hmpName;
121         return ModuleErrorCode::ERR_INVALID_PATH;
122     }
123     if (hmpSet_.find(hmpName) == hmpSet_.end()) {
124         LOG(ERROR) << "Failed to install hmp without preInstall:" << hmpName;
125         return ModuleErrorCode::ERR_INSTALL_FAIL;
126     }
127     int32_t ret = CreateModuleDirs(hmpName);
128     if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
129         RemoveSpecifiedDir(std::string(UPDATE_INSTALL_DIR) + "/" + hmpName, false);
130         return ret;
131     }
132     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
133 }
134 
135 /*
136  * backup activeDir;
137  * new create activeDir;
138  * set param to notify bms update
139  */
PrepareResourceForReboot(const std::string & hmpName) const140 int32_t ModuleUpdateMain::PrepareResourceForReboot(const std::string &hmpName) const
141 {
142     if (installModule_ == nullptr) {
143         LOG(ERROR) << "install module is null";
144         return ModuleErrorCode::ERR_DEAL_HVB_INFO_FAIL;
145     }
146     if (!BackupActiveModules(hmpName)) {
147         LOG(ERROR) << "Failed to backup active hmp: " << hmpName;
148         return ModuleErrorCode::ERR_BACKUP_FAIL;
149     }
150     if (!VerityInfoWrite(*installModule_)) {
151         LOG(ERROR) << "verity info write fail";
152         return ModuleErrorCode::ERR_DEAL_HVB_INFO_FAIL;
153     }
154     std::string hmpActiveDir = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
155     if (SetParameter(BMS_START_INSTALL, BMS_UPDATE) != 0) {
156         LOG(ERROR) << "Failed to set bms scan params: " << hmpActiveDir;
157         return ModuleErrorCode::ERR_SET_PARAM_FAIL;
158     }
159     // create avtive hmp dir finally, avoid to be backup.
160     if (!CreateDirIfNeeded(hmpActiveDir, DIR_MODE)) {
161         LOG(ERROR) << "Failed to create hmp active dir " << hmpActiveDir;
162         return ModuleErrorCode::ERR_CREATE_ACTIVE_FAIL;
163     }
164     sync();
165     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
166 }
167 
ReallyInstallModulePackage(const std::string & pkgPath,const sptr<ISysInstallerCallback> & updateCallback)168 int32_t ModuleUpdateMain::ReallyInstallModulePackage(const std::string &pkgPath,
169     const sptr<ISysInstallerCallback> &updateCallback)
170 {
171     std::string hmpName = GetFileName(pkgPath);
172     int32_t ret = CheckHmpName(hmpName);
173     if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
174         return ret;
175     }
176     std::string hmpDir = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
177     ON_SCOPE_EXIT(rmdir) {
178         RemoveSpecifiedDir(hmpDir, false);
179     };
180     std::string outPath = hmpDir + "/";
181     if (!PrepareFileToDestDir(pkgPath, outPath)) {
182         LOG(ERROR) << "Failed to prepare file, " << pkgPath;
183         return ModuleErrorCode::ERR_INSTALL_FAIL;
184     }
185     std::vector<std::string> files;
186     GetDirFiles(hmpDir, files);
187     int index = 1;
188     for (auto &file : files) {
189         ret = InstallModuleFile(hmpName, file);
190         if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
191             return ret;
192         }
193         if (updateCallback != nullptr) {
194             int percent = static_cast<float>(index) / files.size() * 95;  // 95 : 95% percent
195             updateCallback->OnUpgradeProgress(UpdateStatus::UPDATE_STATE_ONGOING, percent, "");
196         }
197         index++;
198     }
199     ret = PrepareResourceForReboot(hmpName);
200     if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
201         return ret;
202     }
203     CANCEL_SCOPE_EXIT_GUARD(rmdir);
204     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
205 }
206 
ValidateVersion(ModuleFile & installFile,const std::string & hmpName) const207 int32_t ModuleUpdateMain::ValidateVersion(ModuleFile &installFile, const std::string &hmpName) const
208 {
209     std::string preInstalledPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmpName + "/" + HMP_INFO_NAME;
210     std::unique_ptr<ModuleFile> preInstalledFile = ModuleFile::Open(preInstalledPath);
211     if (preInstalledFile == nullptr) {
212         LOG(ERROR) << "Invalid preinstalled file " << preInstalledPath;
213         return ModuleErrorCode::ERR_INSTALL_FAIL;
214     }
215     if (!ModuleFile::CompareVersion(installFile, *preInstalledFile)) {
216         LOG(ERROR) << "Installed version is lower than preInstall.";
217         return ModuleErrorCode::ERR_LOWER_VERSION;
218     }
219     if (!installFile.VerifyModuleVerity()) {
220         LOG(ERROR) << "Failed to verify install img: " << hmpName;
221         return ModuleErrorCode::ERR_VERIFY_FAIL;
222     }
223 
224     std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName + "/" + HMP_INFO_NAME;
225     if (!Utils::IsFileExist(activePath)) {
226         return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
227     }
228     std::unique_ptr<ModuleFile> activeFile = ModuleFile::Open(activePath);
229     if (activeFile == nullptr) {
230         LOG(WARNING) << "Invalid active file " << activePath;
231         return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
232     }
233     if (!ModuleFile::CompareVersion(installFile, *activeFile)) {
234         LOG(ERROR) << "Installed version is lower than active.";
235         return ModuleErrorCode::ERR_LOWER_VERSION;
236     }
237     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
238 }
239 
GetWorkHmpImagePath(const std::string & hmpName)240 std::string ModuleUpdateMain::GetWorkHmpImagePath(const std::string &hmpName)
241 {
242     // Get the path where the latest version is located
243     GetHmpVersionInfo();
244     std::string prefixPath = MODULE_PREINSTALL_DIR;
245     for (const auto &[workHmp, imagePath] : hmpWorkDirMap_) {
246         if (hmpName == workHmp) {
247             prefixPath = imagePath;
248         }
249     }
250     std::string result = prefixPath + "/" + hmpName + "/" + IMG_FILE_NAME;
251     LOG(INFO) << "current work hmp path is " << result;
252     return result;
253 }
254 
InstallModuleFile(const std::string & hmpName,const std::string & file)255 int32_t ModuleUpdateMain::InstallModuleFile(const std::string &hmpName, const std::string &file)
256 {
257     if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
258         return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
259     }
260     std::string fileName = GetFileName(file);
261     if (fileName.empty()) {
262         return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
263     }
264     // verify first, then open module file.
265     if (VerifyModulePackageSign(file) != 0) {
266         LOG(ERROR) << "Verify sign failed " << file;
267         return ModuleErrorCode::ERR_VERIFY_FAIL;
268     }
269 
270     if (IsIncrementPackage(file) && !RestorePackage(file, GetWorkHmpImagePath(hmpName))) {
271         LOG(ERROR) << "Restore package fail: " << file;
272         return ModuleErrorCode::ERR_RESTORE_PACKAGE_FAIL;
273     }
274 
275     std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
276     if (moduleFile == nullptr) {
277         LOG(ERROR) << "Wrong module file " << file << " in hmp package " << hmpName;
278         return ModuleErrorCode::ERR_INSTALL_FAIL;
279     }
280     if (!moduleFile->GetImageStat().has_value()) {
281         LOG(ERROR) << "Could not install empty module package " << moduleFile->GetVersionInfo().version;
282         return ModuleErrorCode::ERR_INSTALL_FAIL;
283     }
284     int32_t ret = ValidateVersion(*moduleFile, hmpName);
285     if (ret != ModuleErrorCode::MODULE_UPDATE_SUCCESS) {
286         LOG(ERROR) << "Validate version fail: " << moduleFile->GetVersionInfo().version;
287         return ret;
288     }
289     installModule_ = std::move(moduleFile);
290 
291     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
292 }
293 
UninstallModulePackage(const std::string & hmpName)294 int32_t ModuleUpdateMain::UninstallModulePackage(const std::string &hmpName)
295 {
296     LOG(INFO) << "UninstallModulePackage " << hmpName;
297     int ret = ModuleErrorCode::MODULE_UPDATE_SUCCESS;
298     if (hmpName.empty() || hmpSet_.find(hmpName) == hmpSet_.end()) {
299         return ModuleErrorCode::ERR_INVALID_PATH;
300     }
301     std::vector<std::string> uninstallDir {UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR, UPDATE_BACKUP_DIR};
302     std::string hmpDir = "/" + hmpName;
303     bool hmpIsValid = false;
304     for (const auto &iter : uninstallDir) {
305         std::string dir = iter + hmpDir;
306         if (!CheckPathExists(dir)) {
307             continue;
308         }
309         hmpIsValid = true;
310         if (!ForceRemoveDirectory(dir)) {
311             LOG(ERROR) << "Failed to remove " << dir;
312             ret = ModuleErrorCode::ERR_UNINSTALL_FAIL;
313         }
314     }
315     if (!hmpIsValid) {
316         ret = ModuleErrorCode::ERR_INVALID_PATH;
317     }
318     return ret;
319 }
320 
GetModulePackageInfo(const std::string & hmpName,std::list<ModulePackageInfo> & modulePackageInfos)321 int32_t ModuleUpdateMain::GetModulePackageInfo(const std::string &hmpName,
322     std::list<ModulePackageInfo> &modulePackageInfos)
323 {
324     LOG(INFO) << "GetModulePackageInfo " << hmpName;
325     if (hmpName.empty()) {
326         for (auto &hmp : hmpSet_) {
327             CollectModulePackageInfo(hmp, modulePackageInfos);
328         }
329     } else if (find(hmpSet_.begin(), hmpSet_.end(), hmpName) != hmpSet_.end()) {
330         CollectModulePackageInfo(hmpName, modulePackageInfos);
331     } else {
332         LOG(ERROR) << hmpName << " not exist in hmpSet";
333         return ModuleErrorCode::MODULE_UPDATE_FAIL;
334     }
335     return ModuleErrorCode::MODULE_UPDATE_SUCCESS;
336 }
337 
CollectModulePackageInfo(const std::string & hmpName,std::list<ModulePackageInfo> & modulePackageInfos) const338 void ModuleUpdateMain::CollectModulePackageInfo(const std::string &hmpName,
339     std::list<ModulePackageInfo> &modulePackageInfos) const
340 {
341     if (hmpName.empty()) {
342         return;
343     }
344     std::string installHmpPath = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
345     std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
346     if (!CheckPathExists(installHmpPath) && !CheckPathExists(activeHmpPath)) {
347         LOG(ERROR) << "hmpName: " << hmpName << " not exist active and install dir.";
348         return;
349     }
350     std::vector<std::string> files;
351     GetDirFiles(installHmpPath, files);
352     GetDirFiles(activeHmpPath, files);
353     for (auto &file : files) {
354         if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
355             continue;
356         }
357         std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
358         if (moduleFile == nullptr) {
359             return;
360         }
361         modulePackageInfos.emplace_back(std::move(moduleFile->GetVersionInfo()));
362     }
363 }
364 
ExitModuleUpdate()365 void ModuleUpdateMain::ExitModuleUpdate()
366 {
367     LOG(INFO) << "ExitModuleUpdate";
368     Stop();
369 }
370 
GetHmpVersion(const std::string & hmpPath,HmpVersionInfo & versionInfo)371 bool ModuleUpdateMain::GetHmpVersion(const std::string &hmpPath, HmpVersionInfo &versionInfo)
372 {
373     LOG(INFO) << "GetHmpVersion " << hmpPath;
374     std::string packInfoPath = hmpPath + "/" + HMP_INFO_NAME;
375     if (!Utils::IsFileExist(packInfoPath)) {
376         LOG(ERROR) << "pack.info is not exist: " << packInfoPath;
377         return false;
378     }
379     if (!StartsWith(packInfoPath, MODULE_PREINSTALL_DIR) &&
380         VerifyModulePackageSign(packInfoPath) != 0) {
381         LOG(ERROR) << "Verify sign failed " << packInfoPath;
382         return false;
383     }
384     std::string packInfo = GetContentFromZip(packInfoPath, PACK_INFO_NAME);
385     JsonNode root(packInfo);
386     const JsonNode &package = root["package"];
387     std::optional<std::string> name = package["name"].As<std::string>();
388     if (!name.has_value()) {
389         LOG(ERROR) << "count get name val";
390         return false;
391     }
392 
393     std::optional<std::string> version = package["version"].As<std::string>();
394     if (!version.has_value()) {
395         LOG(ERROR) << "count get version val";
396         return false;
397     }
398 
399     const JsonNode &laneInfoNode = package["laneInfo"];
400     std::optional<std::string> compatibleVersion = laneInfoNode["compatibleVersion"].As<std::string>();
401     if (!compatibleVersion.has_value()) {
402         LOG(ERROR) << "count get compatibleVersion val";
403         return false;
404     }
405 
406     std::optional<std::string> laneCode = laneInfoNode["laneCode"].As<std::string>();
407     if (!laneCode.has_value()) {
408         LOG(ERROR) << "count get laneCode val";
409         return false;
410     }
411 
412     versionInfo.name = name.value();
413     versionInfo.version = version.value();
414     versionInfo.compatibleVersion = compatibleVersion.value();
415     versionInfo.laneCode = laneCode.value();
416     return true;
417 }
418 
ParseHmpVersionInfo(std::vector<HmpVersionInfo> & versionInfos,const HmpVersionInfo & preInfo,const HmpVersionInfo & actInfo)419 void ModuleUpdateMain::ParseHmpVersionInfo(std::vector<HmpVersionInfo> &versionInfos, const HmpVersionInfo &preInfo,
420     const HmpVersionInfo &actInfo)
421 {
422     if (preInfo.version.size() == 0 && actInfo.version.size() == 0) {
423         LOG(WARNING) << "version is empty";
424         return;
425     }
426 
427     if (actInfo.version.size() == 0) {
428         LOG(INFO) << "add preinstaller info";
429         versionInfos.emplace_back(preInfo);
430         hmpWorkDirMap_.emplace(preInfo.name, MODULE_PREINSTALL_DIR);
431         return;
432     }
433     std::vector<std::string> preVersion {};
434     std::vector<std::string> actVersion {};
435     // version: xxx-d01 M.S.F.B
436     if (!ParseVersion(preInfo.version, " ", preVersion)) {
437         LOG(ERROR) << "Parse preVersion failed.";
438         return;
439     }
440 
441     if (!ParseVersion(actInfo.version, " ", actVersion)) {
442         LOG(WARNING) << "Parse actVersion failed.";
443         versionInfos.emplace_back(preInfo);
444         hmpWorkDirMap_.emplace(preInfo.name, MODULE_PREINSTALL_DIR);
445         return;
446     }
447 
448     if (CompareHmpVersion(preVersion, actVersion)) {
449         LOG(INFO) << "add active info";
450         versionInfos.emplace_back(actInfo);
451         hmpWorkDirMap_.emplace(preInfo.name, UPDATE_ACTIVE_DIR);
452     } else {
453         LOG(INFO) << "add preinstaller info";
454         versionInfos.emplace_back(preInfo);
455         hmpWorkDirMap_.emplace(preInfo.name, MODULE_PREINSTALL_DIR);
456     }
457 }
458 
GetHmpVersionInfo()459 std::vector<HmpVersionInfo> ModuleUpdateMain::GetHmpVersionInfo()
460 {
461     LOG(INFO) << "GetHmpVersionInfo";
462     std::vector<HmpVersionInfo> versionInfos {};
463     ScanPreInstalledHmp();
464     for (auto &hmp : hmpSet_) {
465         std::string preInstallHmpPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmp;
466         std::string activeHmpPath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmp;
467         LOG(INFO) << "preInstallHmpPath:" << preInstallHmpPath << " activeHmpPath:" << activeHmpPath;
468         HmpVersionInfo actinfo {};
469         HmpVersionInfo preinfo {};
470         (void)GetHmpVersion(preInstallHmpPath, preinfo);
471         (void)GetHmpVersion(activeHmpPath, actinfo);
472         ParseHmpVersionInfo(versionInfos, preinfo, actinfo);
473     }
474     return versionInfos;
475 }
476 
SaveInstallerResult(const std::string & hmpPath,int result,const std::string & resultInfo,const Timer & timer)477 void ModuleUpdateMain::SaveInstallerResult(const std::string &hmpPath, int result,
478     const std::string &resultInfo, const Timer &timer)
479 {
480     LOG(INFO) << "hmpPath:" << hmpPath << " result:" << result << " resultInfo:" << resultInfo;
481     UniqueFd fd(open(MODULE_RESULT_PATH, O_APPEND | O_RDWR | O_CREAT | O_CLOEXEC));
482     if (fd.Get() == -1) {
483         LOG(ERROR) << "Failed to open file";
484         return;
485     }
486     constexpr mode_t mode = 0755; // 0755 : rwx-r-x-r-x
487     if (chmod(MODULE_RESULT_PATH, mode) != 0) {
488         LOG(ERROR) << "Could not chmod " << MODULE_RESULT_PATH;
489     }
490     std::string writeInfo = hmpPath + ";" + std::to_string(result) + ";" +
491         resultInfo + "|" + std::to_string(timer.duration().count()) + "\n";
492     if (CheckAndUpdateRevertResult(hmpPath, writeInfo, "revert")) {
493         return;
494     }
495     if (write(fd, writeInfo.data(), writeInfo.length()) <= 0) {
496         LOG(WARNING) << "write result file failed, err:" << errno;
497     }
498     fsync(fd.Get());
499 }
500 
BackupActiveModules(const std::string & hmpName) const501 bool ModuleUpdateMain::BackupActiveModules(const std::string &hmpName) const
502 {
503     std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
504     if (!CheckPathExists(activePath)) {
505         LOG(INFO) << "Nothing to backup, path: " << activePath;
506         return true;
507     }
508     std::string backupPath = std::string(UPDATE_BACKUP_DIR) + "/" + hmpName;
509     if (CheckPathExists(backupPath)) {
510         if (!ForceRemoveDirectory(backupPath)) {
511             LOG(ERROR) << "Failed to remove backup dir:" << backupPath;
512             return false;
513         }
514     }
515     if (!CreateDirIfNeeded(backupPath, DIR_MODE)) {
516         LOG(ERROR) << "Failed to create backup dir:" << backupPath;
517         return false;
518     }
519 
520     std::vector<std::string> activeFiles;
521     GetDirFiles(activePath, activeFiles);
522     ON_SCOPE_EXIT(rmdir) {
523         if (!ForceRemoveDirectory(backupPath)) {
524             LOG(WARNING) << "Failed to remove backup dir when backup failed";
525         }
526     };
527     for (const auto &file : activeFiles) {
528         if (!BackupFile(file)) {
529             return false;
530         }
531     }
532 
533     CANCEL_SCOPE_EXIT_GUARD(rmdir);
534     return true;
535 }
536 
ScanPreInstalledHmp()537 void ModuleUpdateMain::ScanPreInstalledHmp()
538 {
539     std::vector<std::string> files;
540     GetDirFiles(MODULE_PREINSTALL_DIR, files);
541     for (auto &file : files) {
542         if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
543             continue;
544         }
545         std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
546         if (moduleFile == nullptr) {
547             continue;
548         }
549         std::string hmpName = GetHmpName(file);
550         if (hmpName.empty()) {
551             continue;
552         }
553         std::unique_lock<std::mutex> locker(mlock_);
554         LOG(INFO) << "current hmp name: " << hmpName;
555         hmpSet_.emplace(hmpName);
556         for (const auto &[key, value] : moduleFile->GetVersionInfo().moduleMap) {
557             moduleSet_.emplace(key);
558             for (const auto &saInfo : value.saInfoList) {
559                 saIdHmpMap_.emplace(saInfo.saId, key);
560             }
561         }
562     }
563 }
564 
GetSystemAbilityManager()565 sptr<ISystemAbilityManager> &ModuleUpdateMain::GetSystemAbilityManager()
566 {
567     if (samgr_ != nullptr) {
568         return samgr_;
569     }
570     int32_t times = RETRY_TIMES_FOR_SAMGR;
571     constexpr int32_t duration = std::chrono::microseconds(MILLISECONDS_WAITING_SAMGR_ONE_TIME).count();
572     while (times > 0) {
573         times--;
574         samgr_ = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
575         if (samgr_ == nullptr) {
576             LOG(INFO) << "waiting for samgr";
577             usleep(duration);
578         } else {
579             break;
580         }
581     }
582     return samgr_;
583 }
584 
Start()585 void ModuleUpdateMain::Start()
586 {
587     LOG(INFO) << "ModuleUpdateMain Start";
588     ModuleUpdateQueue queue;
589     ModuleUpdateProducer producer(queue, saIdHmpMap_, moduleSet_, g_exit);
590     ModuleUpdateConsumer consumer(queue, saIdHmpMap_, g_exit);
591     std::thread produceThread([&producer] {
592         producer.Run();
593     });
594     std::thread consumeThread([&consumer] {
595         consumer.Run();
596     });
597     consumeThread.join();
598     produceThread.join();
599     LOG(INFO) << "module update main exit";
600 }
601 
Stop()602 void ModuleUpdateMain::Stop()
603 {
604     LOG(INFO) << "ModuleUpdateMain Stop";
605     g_exit = 1;
606 }
607 } // namespace SysInstaller
608 } // namespace OHOS