1 /*
2  * Copyright (c) 2024 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_consumer.h"
17 #include <vector>
18 #include "directory_ex.h"
19 #include "log/log.h"
20 #include "module_constants.h"
21 #include "module_error_code.h"
22 #include "module_update.h"
23 #include "module_update_main.h"
24 #include "module_utils.h"
25 #include "parameter.h"
26 #include "scope_guard.h"
27 
28 namespace OHOS {
29 namespace SysInstaller {
30 using namespace Updater;
31 
ModuleUpdateConsumer(ModuleUpdateQueue & queue,std::unordered_map<int32_t,std::string> & saIdHmpMap,volatile sig_atomic_t & exit)32 ModuleUpdateConsumer::ModuleUpdateConsumer(ModuleUpdateQueue &queue,
33     std::unordered_map<int32_t, std::string> &saIdHmpMap, volatile sig_atomic_t &exit)
34     : queue_(queue),
35       saIdHmpMap_(saIdHmpMap),
36       exit_(exit) {}
37 
DoInstall(ModuleUpdateStatus & status)38 void ModuleUpdateConsumer::DoInstall(ModuleUpdateStatus &status)
39 {
40     ON_SCOPE_EXIT(rmdir) {
41         RemoveSpecifiedDir(std::string(UPDATE_INSTALL_DIR) + "/" + status.hmpName);
42     };
43     if (ModuleUpdate::GetInstance().DoModuleUpdate(status)) {
44         LOG(INFO) << "hmp package successful install, hmp name=" << status.hmpName;
45     } else {
46         LOG(ERROR) << "hmp package fail install, hmp name=" << status.hmpName;
47     }
48 }
49 
DoRevert(const std::string & hmpName,int32_t saId)50 void ModuleUpdateConsumer::DoRevert(const std::string &hmpName, int32_t saId)
51 {
52     LOG(INFO) << "hmp package revert,hmp name=" << hmpName << "; said=" << saId;
53     bool isHotHmp = IsHotHmpPackage(hmpName);
54     ModuleUpdateStatus status;
55     status.hmpName = hmpName;
56     status.isHotInstall = isHotHmp;
57     Revert(hmpName, !isHotHmp);
58     DoInstall(status);
59 }
60 
DoUnload(const std::string & hmpName,int32_t saId)61 void ModuleUpdateConsumer::DoUnload(const std::string &hmpName, int32_t saId)
62 {
63     LOG(INFO) << "hmp package unload,hmp name=" << hmpName << "; said=" << saId;
64     ModuleUpdateStatus status;
65     status.hmpName = hmpName;
66     status.isHotInstall = true;
67     if (IsRunning(saId)) {
68         LOG(INFO) << "sa is running, saId=" << saId;
69         return;
70     }
71     // check whether install hmp exists
72     DoInstall(status);
73 }
74 
Run()75 void ModuleUpdateConsumer::Run()
76 {
77     LOG(INFO) << "ModuleUpdateConsumer Consume";
78     do {
79         if (exit_ == 1 && queue_.IsEmpty()) {
80             queue_.Stop();
81             break;
82         }
83         std::pair<int32_t, std::string> saStatusPair = queue_.Pop();
84         if (saStatusPair.first == 0 && saStatusPair.second == "") {
85             LOG(INFO) << "producer and consumer stop";
86             break;
87         }
88         Timer timer;
89         if (saStatusPair.first == APP_SERIAL_NUMBER) {
90             ModuleUpdateMain::GetInstance().SaveInstallerResult(saStatusPair.second, ModuleErrorCode::ERR_BMS_REVERT,
91                 saStatusPair.second + " revert", timer);
92             DoRevert(saStatusPair.second, APP_SERIAL_NUMBER);
93             continue;
94         }
95         int32_t saId = saStatusPair.first;
96         std::string saStatus = saStatusPair.second;
97         auto it = saIdHmpMap_.find(saId);
98         if (it == saIdHmpMap_.end() || it->second == "") {
99             LOG(ERROR) << "find hmp fail, saId=" << saId;
100             continue;
101         }
102         std::string hmpName = it->second;
103         if (strcmp(saStatus.c_str(), LOAD_FAIL) == 0 || strcmp(saStatus.c_str(), CRASH) == 0) {
104             ModuleUpdateMain::GetInstance().SaveInstallerResult(hmpName, ModuleErrorCode::ERR_SAMGR_REVERT,
105                 std::to_string(saId) + " revert", timer);
106             DoRevert(hmpName, saId);
107         } else if (IsHotSa(saId) && strcmp(saStatus.c_str(), UNLOAD) == 0) {
108             DoUnload(hmpName, saId);
109         } else {
110             LOG(ERROR) << "sa status not exist, said=" << saId;
111         }
112     } while (true);
113     LOG(INFO) << "consumer exit";
114 }
115 } // SysInstaller
116 } // namespace OHOS