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 <cstring>
17 #include <dirent.h>
18
19 #include "hmp_bundle_installer.h"
20
21 #include "app_log_wrapper.h"
22 #include "app_service_fwk_installer.h"
23 #include "bundle_constants.h"
24 #include "bundle_data_mgr.h"
25 #include "bundle_parser.h"
26 #include "bundle_service_constants.h"
27 #include "bundle_mgr_service.h"
28
29 namespace OHOS {
30 namespace AppExecFwk {
31 namespace {
32 const std::string APP_DIR = "/app";
33 const std::string APP_SERVICE_FWK_DIR = "appServiceFwk";
34 const std::string HAP_PATH_DATA_AREA = "/data/app/el1/bundle/public";
35 } // namespace
36
HmpBundleInstaller()37 HmpBundleInstaller::HmpBundleInstaller()
38 {
39 APP_LOGD("hmp bundle installer instance is created");
40 }
41
~HmpBundleInstaller()42 HmpBundleInstaller::~HmpBundleInstaller()
43 {
44 APP_LOGD("hmp bundle installer instance is destroyed");
45 }
46
GetHmpBundleList(const std::string &path) const47 std::set<std::string> HmpBundleInstaller::GetHmpBundleList(const std::string &path) const
48 {
49 std::set<std::string> hmpBundleList;
50 DIR *dir = opendir(path.c_str());
51 if (dir == nullptr) {
52 APP_LOGE("fail to opendir:%{public}s, errno:%{public}d", path.c_str(), errno);
53 return hmpBundleList;
54 }
55 struct dirent *ptr;
56 while ((ptr = readdir(dir)) != nullptr) {
57 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0 ||
58 strcmp(ptr->d_name, APP_SERVICE_FWK_DIR.c_str()) == 0) {
59 continue;
60 }
61 if (ptr->d_type == DT_DIR) {
62 hmpBundleList.insert(std::string(ptr->d_name));
63 continue;
64 }
65 }
66 closedir(dir);
67 return hmpBundleList;
68 }
69
InstallSystemHspInHmp(const std::string &bundleDir) const70 ErrCode HmpBundleInstaller::InstallSystemHspInHmp(const std::string &bundleDir) const
71 {
72 AppServiceFwkInstaller installer;
73 InstallParam installParam;
74 installParam.isPreInstallApp = true;
75 installParam.removable = false;
76 installParam.copyHapToInstallPath = false;
77 installParam.needSavePreInstallInfo = true;
78 ErrCode ret = installer.Install({ bundleDir }, installParam);
79 if (ret != ERR_OK) {
80 APP_LOGE("install hmp system hsp %{public}s error with code: %{public}d", bundleDir.c_str(), ret);
81 }
82 return ret;
83 }
84
InstallNormalAppInHmp(const std::string &bundleDir, bool removable)85 ErrCode HmpBundleInstaller::InstallNormalAppInHmp(const std::string &bundleDir, bool removable)
86 {
87 auto pos = bundleDir.rfind('/');
88 auto bundleName = pos != std::string::npos ? bundleDir.substr(pos + 1) : "";
89 std::set<int32_t> requiredUserIds;
90 if (!GetRequiredUserIds(bundleName, requiredUserIds)) {
91 APP_LOGI("%{public}s need not to install", bundleDir.c_str());
92 return ERR_OK;
93 }
94 InstallParam installParam;
95 installParam.isPreInstallApp = true;
96 installParam.SetKillProcess(false);
97 installParam.needSendEvent = true;
98 installParam.needSavePreInstallInfo = true;
99 installParam.copyHapToInstallPath = false;
100 installParam.userId = Constants::DEFAULT_USERID;
101 installParam.installFlag = InstallFlag::REPLACE_EXISTING;
102 installParam.isOTA = true;
103 installParam.removable = removable;
104 installParam.preinstallSourceFlag = ApplicationInfoFlag::FLAG_OTA_INSTALLED;
105 ErrCode ret = InstallBundle(bundleDir, installParam, Constants::AppType::SYSTEM_APP);
106 ResetInstallProperties();
107 if (ret == ERR_OK) {
108 APP_LOGI("install hmp normal app %{public}s for user 0 success", bundleDir.c_str());
109 return ret;
110 }
111 if (!InitDataMgr()) {
112 return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR;
113 }
114 if (dataMgr_->IsSystemHsp(bundleName)) {
115 APP_LOGE("install hmp system hsp %{public}s error with code: %{public}d", bundleDir.c_str(), ret);
116 return ret;
117 }
118 bool installSuccess = false;
119 for (auto userId : requiredUserIds) {
120 if (userId == Constants::DEFAULT_USERID) {
121 continue;
122 }
123 installParam.userId = userId;
124 ret = InstallBundle(bundleDir, installParam, Constants::AppType::SYSTEM_APP);
125 ResetInstallProperties();
126 APP_LOGI("install hmp bundleName: %{public}s, userId: %{public}d, result: %{public}d",
127 bundleName.c_str(), userId, ret);
128 if (ret != ERR_OK) {
129 APP_LOGE("install hmp normal app %{public}s error with code: %{public}d", bundleDir.c_str(), ret);
130 return ret;
131 }
132 installSuccess = true;
133 }
134 return installSuccess ? ERR_OK : ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
135 }
136
GetRequiredUserIds(std::string bundleName, std::set<int32_t> &userIds)137 bool HmpBundleInstaller::GetRequiredUserIds(std::string bundleName, std::set<int32_t> &userIds)
138 {
139 if (!InitDataMgr()) {
140 return false;
141 }
142 // if bundle exists, return the set of user ids that have installed the bundle
143 if (dataMgr_->GetInnerBundleInfoUsers(bundleName, userIds)) {
144 return true;
145 }
146 // if bundle does not exist, check whether the bundle is pre-installed
147 // if so, it means the bundle is uninstalled by all users, return empty set
148 PreInstallBundleInfo preInfo;
149 if (dataMgr_->GetPreInstallBundleInfo(bundleName, preInfo)) {
150 return false;
151 }
152 // if bundle does not exist and is not pre-installed, it means the bundle is new, return all user ids
153 for (auto userId : dataMgr_->GetAllUser()) {
154 if (userId >= Constants::START_USERID) {
155 userIds.insert(userId);
156 }
157 }
158 return true;
159 }
160
CheckAppIsUpdatedByUser(const std::string &bundleName)161 bool HmpBundleInstaller::CheckAppIsUpdatedByUser(const std::string &bundleName)
162 {
163 if (bundleName.empty()) {
164 APP_LOGE("name empty");
165 return false;
166 }
167 if (!InitDataMgr()) {
168 APP_LOGE("init dataMgr failed");
169 return false;
170 }
171 BundleInfo bundleInfo;
172 auto baseFlag = static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) +
173 static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_DISABLE);
174 ErrCode ret = dataMgr_->GetBundleInfoV9(bundleName, baseFlag, bundleInfo, Constants::ANY_USERID);
175 if (ret != ERR_OK) {
176 APP_LOGW("%{public}s not found", bundleName.c_str());
177 return false;
178 }
179 for (const auto &hapInfo : bundleInfo.hapModuleInfos) {
180 if (hapInfo.hapPath.size() > HAP_PATH_DATA_AREA.size() &&
181 hapInfo.hapPath.compare(0, HAP_PATH_DATA_AREA.size(), HAP_PATH_DATA_AREA) == 0) {
182 APP_LOGI("%{public}s has been updated by user", hapInfo.name.c_str());
183 return true;
184 }
185 }
186 APP_LOGI("%{public}s has not been updated by user", bundleName.c_str());
187 return false;
188 }
189
RollbackHmpBundle(const std::set<std::string> &systemHspList, const std::set<std::string> &hapList)190 void HmpBundleInstaller::RollbackHmpBundle(const std::set<std::string> &systemHspList,
191 const std::set<std::string> &hapList)
192 {
193 std::set<std::string> rollbackList;
194 for (const auto &bundleName : hapList) {
195 if (!CheckAppIsUpdatedByUser(bundleName)) {
196 rollbackList.insert(bundleName);
197 }
198 }
199 // If the update fails, the information of the application in the database needs to be deleted,
200 // but the user data directory and some settings set by the user,
201 // such as app control rules and default applications, cannot be deleted.
202 std::set<std::string> normalBundleList;
203 std::set_difference(rollbackList.begin(), rollbackList.end(), systemHspList.begin(), systemHspList.end(),
204 std::inserter(normalBundleList, normalBundleList.begin()));
205 for (const auto &bundleName : normalBundleList) {
206 ErrCode ret = RollbackHmpUserInfo(bundleName);
207 if (ret != ERR_OK) {
208 APP_LOGE("RollbackHmpUserInfo %{public}s error with code: %{public}d", bundleName.c_str(), ret);
209 }
210 }
211 std::set<std::string> allBundleList;
212 allBundleList.insert(systemHspList.begin(), systemHspList.end());
213 allBundleList.insert(rollbackList.begin(), rollbackList.end());
214 for (const auto &bundleName : allBundleList) {
215 ErrCode ret = RollbackHmpCommonInfo(bundleName);
216 if (ret != ERR_OK) {
217 APP_LOGE("RollbackHmpCommonInfo %{public}s error with code: %{public}d", bundleName.c_str(), ret);
218 }
219 }
220 }
221
ParseHapFiles( const std::string &hapFilePath, std::unordered_map<std::string, InnerBundleInfo> &infos)222 bool HmpBundleInstaller::ParseHapFiles(
223 const std::string &hapFilePath,
224 std::unordered_map<std::string, InnerBundleInfo> &infos)
225 {
226 std::vector<std::string> hapFilePathVec { hapFilePath };
227 std::vector<std::string> realPaths;
228 auto ret = BundleUtil::CheckFilePath(hapFilePathVec, realPaths);
229 if (ret != ERR_OK) {
230 APP_LOGE("File path %{public}s invalid", hapFilePath.c_str());
231 return false;
232 }
233
234 BundleParser bundleParser;
235 for (auto realPath : realPaths) {
236 InnerBundleInfo innerBundleInfo;
237 ret = bundleParser.Parse(realPath, innerBundleInfo);
238 if (ret != ERR_OK) {
239 APP_LOGE("Parse bundle info failed, error: %{public}d", ret);
240 continue;
241 }
242
243 infos.emplace(realPath, innerBundleInfo);
244 }
245
246 if (infos.empty()) {
247 APP_LOGE("Parse hap(%{public}s) empty ", hapFilePath.c_str());
248 return false;
249 }
250
251 return true;
252 }
253
ParseInfos(const std::string &bundleDir, const std::string &hspDir, std::unordered_map<std::string, InnerBundleInfo> &infos)254 void HmpBundleInstaller::ParseInfos(const std::string &bundleDir, const std::string &hspDir,
255 std::unordered_map<std::string, InnerBundleInfo> &infos)
256 {
257 if (!bundleDir.empty()) {
258 if (!ParseHapFiles(bundleDir, infos) || infos.empty()) {
259 APP_LOGW("obtain bundleinfo failed : %{public}s ", bundleDir.c_str());
260 }
261 }
262 if (!hspDir.empty()) {
263 if (!ParseHapFiles(hspDir, infos) || infos.empty()) {
264 APP_LOGW("obtain appService bundleinfo failed : %{public}s ", hspDir.c_str());
265 }
266 }
267 }
268
UpdateBundleInfo(const std::string &bundleName, const std::string &bundleDir, const std::string &hspDir)269 void HmpBundleInstaller::UpdateBundleInfo(const std::string &bundleName,
270 const std::string &bundleDir, const std::string &hspDir)
271 {
272 std::unordered_map<std::string, InnerBundleInfo> infos;
273 ParseInfos(bundleDir, hspDir, infos);
274 UpdateInnerBundleInfo(bundleName, infos);
275 UpdatePreInfoInDb(bundleName, infos);
276 }
277
UpdateInnerBundleInfo(const std::string &bundleName, const std::unordered_map<std::string, InnerBundleInfo> &infos)278 void HmpBundleInstaller::UpdateInnerBundleInfo(const std::string &bundleName,
279 const std::unordered_map<std::string, InnerBundleInfo> &infos)
280 {
281 if (!InitDataMgr()) {
282 return;
283 }
284 InnerBundleInfo oldBundleInfo;
285 bool hasInstalled = dataMgr_->FetchInnerBundleInfo(bundleName, oldBundleInfo);
286 if (!hasInstalled) {
287 APP_LOGW("app(%{public}s) has been uninstalled", bundleName.c_str());
288 return;
289 }
290 auto innerModuleInfos = oldBundleInfo.GetInnerModuleInfos();
291 std::set<std::string> newModulePackages;
292 for (const auto &item : infos) {
293 newModulePackages.insert(item.second.GetCurrentModulePackage());
294 }
295 for (const auto &item : innerModuleInfos) {
296 if (newModulePackages.find(item.first) == newModulePackages.end()) {
297 APP_LOGI("module package (%{public}s) need to be removed.", item.first.c_str());
298 if (!UninstallSystemBundle(bundleName, item.first)) {
299 APP_LOGW("uninstall module %{public}s for bundle %{public}s failed",
300 item.first.c_str(), bundleName.c_str());
301 }
302 }
303 }
304 }
305
UninstallSystemBundle(const std::string &bundleName, const std::string &modulePackage)306 bool HmpBundleInstaller::UninstallSystemBundle(const std::string &bundleName, const std::string &modulePackage)
307 {
308 if (!InitDataMgr()) {
309 return false;
310 }
311
312 InstallParam installParam;
313 bool uninstallResult = false;
314 for (auto userId : dataMgr_->GetAllUser()) {
315 installParam.userId = userId;
316 installParam.needSavePreInstallInfo = true;
317 installParam.isPreInstallApp = true;
318 installParam.SetKillProcess(false);
319 installParam.needSendEvent = false;
320 MarkPreBundleSyeEventBootTag(false);
321 ErrCode result = UninstallBundle(bundleName, modulePackage, installParam);
322 ResetInstallProperties();
323 if (result != ERR_OK) {
324 APP_LOGW("uninstall system bundle fail for userId %{public}d, error: %{public}d", userId, result);
325 continue;
326 }
327 APP_LOGI("uninstall module %{public}s success", modulePackage.c_str());
328 uninstallResult = true;
329 }
330 CheckUninstallSystemHsp(bundleName);
331
332 return uninstallResult;
333 }
334
CheckUninstallSystemHsp(const std::string &bundleName)335 void HmpBundleInstaller::CheckUninstallSystemHsp(const std::string &bundleName)
336 {
337 if (!InitDataMgr()) {
338 return;
339 }
340 InnerBundleInfo info;
341 if (!(dataMgr_->FetchInnerBundleInfo(bundleName, info))) {
342 APP_LOGD("bundleName %{public}s not existed local", bundleName.c_str());
343 return;
344 }
345 if (info.GetApplicationBundleType() != BundleType::APP_SERVICE_FWK) {
346 APP_LOGD("bundleName %{public}s is not a system hsp", bundleName.c_str());
347 return;
348 }
349 bool isExistHsp = false;
350 for (const auto &item : info.GetInnerModuleInfos()) {
351 if (item.second.distro.moduleType == "shared") {
352 isExistHsp = true;
353 return;
354 }
355 }
356 APP_LOGI("appService %{public}s does not have any hsp, so it need to be uninstalled.", bundleName.c_str());
357 if (!isExistHsp) {
358 InstallParam installParam;
359 installParam.userId = Constants::DEFAULT_USERID;
360 installParam.needSavePreInstallInfo = true;
361 installParam.isPreInstallApp = true;
362 installParam.SetKillProcess(false);
363 installParam.needSendEvent = false;
364 installParam.isKeepData = true;
365 MarkPreBundleSyeEventBootTag(false);
366 ErrCode result = UninstallBundle(bundleName, installParam);
367 if (result != ERR_OK) {
368 APP_LOGW("uninstall system bundle fail, error: %{public}d", result);
369 return;
370 }
371 PreInstallBundleInfo preInstallBundleInfo;
372 if ((dataMgr_->GetPreInstallBundleInfo(bundleName, preInstallBundleInfo))) {
373 dataMgr_->DeletePreInstallBundleInfo(bundleName, preInstallBundleInfo);
374 }
375 }
376 }
377
UpdatePreInfoInDb(const std::string &bundleName, const std::unordered_map<std::string, InnerBundleInfo> &infos)378 void HmpBundleInstaller::UpdatePreInfoInDb(const std::string &bundleName,
379 const std::unordered_map<std::string, InnerBundleInfo> &infos)
380 {
381 if (!InitDataMgr()) {
382 return;
383 }
384 PreInstallBundleInfo preInstallBundleInfo;
385 dataMgr_->GetPreInstallBundleInfo(bundleName, preInstallBundleInfo);
386 auto bundlePathList = preInstallBundleInfo.GetBundlePaths();
387 for (const std::string &bundlePath : bundlePathList) {
388 if (infos.find(bundlePath) == infos.end()) {
389 APP_LOGI("bundlePath %{public}s need to be deleted", bundlePath.c_str());
390 preInstallBundleInfo.DeleteBundlePath(bundlePath);
391 }
392 }
393 if (preInstallBundleInfo.GetBundlePaths().empty()) {
394 dataMgr_->DeletePreInstallBundleInfo(bundleName, preInstallBundleInfo);
395 } else {
396 dataMgr_->SavePreInstallBundleInfo(bundleName, preInstallBundleInfo);
397 }
398 }
399
UpdateBundleInfoForHmp(const std::string &filePath, std::set<std::string> hapList, std::set<std::string> systemHspList)400 void HmpBundleInstaller::UpdateBundleInfoForHmp(const std::string &filePath, std::set<std::string> hapList,
401 std::set<std::string> systemHspList)
402 {
403 std::string appBaseDir = filePath + APP_DIR;
404 std::string appServiceFwkBaseDir = filePath + APP_DIR + ServiceConstants::PATH_SEPARATOR + APP_SERVICE_FWK_DIR;
405 for (const auto &bundleName : hapList) {
406 std::string bundleDir = appBaseDir + ServiceConstants::PATH_SEPARATOR + bundleName;
407 std::string hspDir = "";
408 if (systemHspList.find(bundleName) != systemHspList.end()) {
409 hspDir = appServiceFwkBaseDir + ServiceConstants::PATH_SEPARATOR + bundleName;
410 }
411 UpdateBundleInfo(bundleName, bundleDir, hspDir);
412 }
413
414 for (const auto &bundleName : systemHspList) {
415 if (hapList.find(bundleName) == hapList.end()) {
416 std::string hspDir = appServiceFwkBaseDir + ServiceConstants::PATH_SEPARATOR + bundleName;
417 UpdateBundleInfo(bundleName, "", hspDir);
418 }
419 }
420 }
421
GetIsRemovable(const std::string &bundleName)422 bool HmpBundleInstaller::GetIsRemovable(const std::string &bundleName)
423 {
424 if (!InitDataMgr()) {
425 return true;
426 }
427 InnerBundleInfo info;
428 if (!dataMgr_->FetchInnerBundleInfo(bundleName, info)) {
429 APP_LOGE("get removable failed %{public}s", bundleName.c_str());
430 return true;
431 }
432 return info.IsRemovable();
433 }
434
InitDataMgr()435 bool HmpBundleInstaller::InitDataMgr()
436 {
437 if (dataMgr_ == nullptr) {
438 dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
439 if (dataMgr_ == nullptr) {
440 APP_LOGE("Get dataMgr_ nullptr");
441 return false;
442 }
443 }
444 return true;
445 }
446 } // namespace AppExecFwk
447 } // namespace OHOS
448