1 /*
2 * Copyright (c) 2021-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 "bundle_installer_manager.h"
17
18 #include "app_log_tag_wrapper.h"
19 #include "bundle_memory_guard.h"
20 #include "bundle_mgr_service.h"
21 #include "datetime_ex.h"
22 #include "ipc_skeleton.h"
23 #include "xcollie_helper.h"
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 constexpr const char* INSTALL_TASK = "Install_Task";
29 constexpr const char* UNINSTALL_TASK = "Uninstall_Task";
30 constexpr const char* RECOVER_TASK = "Recover_Task";
31 constexpr const char* THREAD_POOL_NAME = "InstallerThreadPool";
32 constexpr unsigned int TIME_OUT_SECONDS = 60 * 25;
33 constexpr int8_t MAX_TASK_NUMBER = 10;
34 constexpr int8_t DELAY_INTERVAL_SECONDS = 60;
35 static std::atomic<int32_t> g_taskCounter = 0;
36 }
37
BundleInstallerManager()38 BundleInstallerManager::BundleInstallerManager()
39 {
40 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "create bundle installer manager instance");
41 }
42
~BundleInstallerManager()43 BundleInstallerManager::~BundleInstallerManager()
44 {
45 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "destroy bundle installer manager instance");
46 }
47
CreateInstallTask(const std::string & bundleFilePath,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)48 void BundleInstallerManager::CreateInstallTask(
49 const std::string &bundleFilePath, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
50 {
51 auto installer = CreateInstaller(statusReceiver);
52 if (installer == nullptr) {
53 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
54 return;
55 }
56 auto task = [installer, bundleFilePath, installParam] {
57 BundleMemoryGuard memoryGuard;
58 int32_t timerId = XCollieHelper::SetTimer(INSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
59 installer->Install(bundleFilePath, installParam);
60 g_taskCounter--;
61 XCollieHelper::CancelTimer(timerId);
62 };
63 AddTask(task, "InstallTask path:" + bundleFilePath);
64 }
65
CreateRecoverTask(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)66 void BundleInstallerManager::CreateRecoverTask(
67 const std::string &bundleName, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
68 {
69 auto installer = CreateInstaller(statusReceiver);
70 if (installer == nullptr) {
71 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
72 return;
73 }
74 auto task = [installer, bundleName, installParam] {
75 BundleMemoryGuard memoryGuard;
76 int32_t timerId = XCollieHelper::SetTimer(RECOVER_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
77 installer->Recover(bundleName, installParam);
78 g_taskCounter--;
79 XCollieHelper::CancelTimer(timerId);
80 };
81 AddTask(task, "RecoverTask -n " + bundleName);
82 }
83
CreateInstallTask(const std::vector<std::string> & bundleFilePaths,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)84 void BundleInstallerManager::CreateInstallTask(const std::vector<std::string> &bundleFilePaths,
85 const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
86 {
87 auto installer = CreateInstaller(statusReceiver);
88 if (installer == nullptr) {
89 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
90 return;
91 }
92 auto task = [installer, bundleFilePaths, installParam] {
93 BundleMemoryGuard memoryGuard;
94 int32_t timerId = XCollieHelper::SetTimer(INSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
95 installer->Install(bundleFilePaths, installParam);
96 g_taskCounter--;
97 XCollieHelper::CancelTimer(timerId);
98 };
99 std::string paths;
100 for (const auto &bundleFilePath : bundleFilePaths) {
101 paths.append(bundleFilePath).append(" ");
102 }
103 AddTask(task, "InstallTask path:" + paths);
104 }
105
CreateInstallByBundleNameTask(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)106 void BundleInstallerManager::CreateInstallByBundleNameTask(const std::string &bundleName,
107 const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
108 {
109 auto installer = CreateInstaller(statusReceiver);
110 if (installer == nullptr) {
111 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
112 return;
113 }
114
115 auto task = [installer, bundleName, installParam] {
116 BundleMemoryGuard memoryGuard;
117 int32_t timerId = XCollieHelper::SetTimer(INSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
118 installer->InstallByBundleName(bundleName, installParam);
119 g_taskCounter--;
120 XCollieHelper::CancelTimer(timerId);
121 };
122 AddTask(task, "InstallTask -n " + bundleName);
123 }
124
CreateUninstallTask(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)125 void BundleInstallerManager::CreateUninstallTask(
126 const std::string &bundleName, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
127 {
128 auto installer = CreateInstaller(statusReceiver);
129 if (installer == nullptr) {
130 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
131 return;
132 }
133 auto task = [installer, bundleName, installParam] {
134 BundleMemoryGuard memoryGuard;
135 int32_t timerId = XCollieHelper::SetTimer(UNINSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
136 installer->Uninstall(bundleName, installParam);
137 g_taskCounter--;
138 XCollieHelper::CancelTimer(timerId);
139 };
140 AddTask(task, "UninstallTask -n " + bundleName);
141 }
142
CreateUninstallTask(const std::string & bundleName,const std::string & modulePackage,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)143 void BundleInstallerManager::CreateUninstallTask(const std::string &bundleName, const std::string &modulePackage,
144 const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
145 {
146 auto installer = CreateInstaller(statusReceiver);
147 if (installer == nullptr) {
148 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
149 return;
150 }
151 auto task = [installer, bundleName, modulePackage, installParam] {
152 BundleMemoryGuard memoryGuard;
153 int32_t timerId = XCollieHelper::SetTimer(UNINSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
154 installer->Uninstall(bundleName, modulePackage, installParam);
155 g_taskCounter--;
156 XCollieHelper::CancelTimer(timerId);
157 };
158 AddTask(task, "UninstallTask -n " + bundleName);
159 }
160
CreateUninstallTask(const UninstallParam & uninstallParam,const sptr<IStatusReceiver> & statusReceive)161 void BundleInstallerManager::CreateUninstallTask(const UninstallParam &uninstallParam,
162 const sptr<IStatusReceiver> &statusReceive)
163 {
164 auto installer = CreateInstaller(statusReceive);
165 if (installer == nullptr) {
166 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
167 return;
168 }
169 auto task = [installer, uninstallParam] {
170 BundleMemoryGuard memoryGuard;
171 int32_t timerId = XCollieHelper::SetTimer(UNINSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
172 installer->Uninstall(uninstallParam);
173 g_taskCounter--;
174 XCollieHelper::CancelTimer(timerId);
175 };
176 AddTask(task, "UninstallTask -n " + uninstallParam.bundleName);
177 }
178
CreateUninstallAndRecoverTask(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)179 void BundleInstallerManager::CreateUninstallAndRecoverTask(const std::string &bundleName,
180 const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
181 {
182 auto installer = CreateInstaller(statusReceiver);
183 if (installer == nullptr) {
184 LOG_E(BMS_TAG_INSTALLER, "create installer failed");
185 return;
186 }
187 auto task = [installer, bundleName, installParam] {
188 BundleMemoryGuard memoryGuard;
189 int32_t timerId = XCollieHelper::SetTimer(UNINSTALL_TASK, TIME_OUT_SECONDS, nullptr, nullptr);
190 installer->UninstallAndRecover(bundleName, installParam);
191 g_taskCounter--;
192 XCollieHelper::CancelTimer(timerId);
193 };
194 AddTask(task, "UninstallAndRecover -n " + bundleName);
195 }
196
CreateInstaller(const sptr<IStatusReceiver> & statusReceiver)197 std::shared_ptr<BundleInstaller> BundleInstallerManager::CreateInstaller(const sptr<IStatusReceiver> &statusReceiver)
198 {
199 int64_t installerId = GetMicroTickCount();
200 auto installer = std::make_shared<BundleInstaller>(installerId, statusReceiver);
201 installer->SetCallingUid(IPCSkeleton::GetCallingUid());
202 return installer;
203 }
204
AddTask(const ThreadPoolTask & task,const std::string & taskName)205 void BundleInstallerManager::AddTask(const ThreadPoolTask &task, const std::string &taskName)
206 {
207 std::lock_guard<std::mutex> guard(mutex_);
208 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "hold mutex");
209 if (threadPool_ == nullptr) {
210 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "begin to start InstallerThreadPool");
211 threadPool_ = std::make_shared<ThreadPool>(THREAD_POOL_NAME);
212 threadPool_->Start(THREAD_NUMBER);
213 threadPool_->SetMaxTaskNum(MAX_TASK_NUMBER);
214 auto delayCloseTask = std::bind(&BundleInstallerManager::DelayStopThreadPool, shared_from_this());
215 std::thread t(delayCloseTask);
216 t.detach();
217 }
218 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "add task taskName:%{public}s", taskName.c_str());
219 g_taskCounter++;
220 threadPool_->AddTask(task);
221 }
222
DelayStopThreadPool()223 void BundleInstallerManager::DelayStopThreadPool()
224 {
225 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "DelayStopThreadPool begin");
226 BundleMemoryGuard memoryGuard;
227
228 do {
229 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "sleep for 60s runningTask %{public}d", g_taskCounter.load());
230 std::this_thread::sleep_for(std::chrono::seconds(DELAY_INTERVAL_SECONDS));
231 } while (threadPool_ != nullptr && (threadPool_->GetCurTaskNum() != 0
232 || g_taskCounter.load() != 0));
233
234 std::lock_guard<std::mutex> guard(mutex_);
235 if (threadPool_ == nullptr) {
236 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "InstallerThreadPool is null, no need to stop");
237 return;
238 }
239 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "begin to stop InstallerThreadPool");
240 threadPool_->Stop();
241 threadPool_ = nullptr;
242 LOG_NOFUNC_I(BMS_TAG_INSTALLER, "DelayStopThreadPool end");
243 }
244
GetCurTaskNum()245 size_t BundleInstallerManager::GetCurTaskNum()
246 {
247 std::lock_guard<std::mutex> guard(mutex_);
248 if (threadPool_ == nullptr) {
249 return 0;
250 }
251
252 return threadPool_->GetCurTaskNum();
253 }
254 } // namespace AppExecFwk
255 } // namespace OHOS