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