• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "extend_resource_manager_host_impl.h"
17 
18 #include "account_helper.h"
19 #include "bundle_constants.h"
20 #include "bundle_mgr_service.h"
21 #include "bundle_parser.h"
22 #include "bundle_permission_mgr.h"
23 #ifdef BUNDLE_FRAMEWORK_BUNDLE_RESOURCE
24 #include "bundle_resource/bundle_resource_manager.h"
25 #include "bundle_resource/bundle_resource_process.h"
26 #include "bundle_resource/bundle_resource_parser.h"
27 #include "bundle_resource/resource_info.h"
28 #endif
29 #include "installd_client.h"
30 
31 namespace OHOS {
32 namespace AppExecFwk {
33 namespace {
34 const char* SEPARATOR = "/";
35 constexpr const char* EXT_RESOURCE_FILE_SUFFIX = ".hsp";
36 
IsFileNameValid(const std::string & fileName)37 bool IsFileNameValid(const std::string &fileName)
38 {
39     if (fileName.find("..") != std::string::npos
40         || fileName.find("/") != std::string::npos
41         || fileName.find("\\") != std::string::npos
42         || fileName.find("%") != std::string::npos) {
43         return false;
44     }
45     return true;
46 }
47 
IsValidPath(const std::string & path)48 bool IsValidPath(const std::string &path)
49 {
50     if (path.find("..") != std::string::npos) {
51         return false;
52     }
53     return true;
54 }
55 
GetFileName(const std::string & sourcePath)56 std::string GetFileName(const std::string &sourcePath)
57 {
58     size_t pos = sourcePath.find_last_of(SEPARATOR);
59     if (pos == std::string::npos) {
60         APP_LOGE("invalid sourcePath %{public}s", sourcePath.c_str());
61         return sourcePath;
62     }
63     return sourcePath.substr(pos + 1);
64 }
65 
BuildResourcePath(const std::string & bundleName)66 std::string BuildResourcePath(const std::string &bundleName)
67 {
68     std::string filePath;
69     filePath.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
70         .append(bundleName).append(ServiceConstants::PATH_SEPARATOR)
71         .append(ServiceConstants::EXT_RESOURCE_FILE_PATH).append(ServiceConstants::PATH_SEPARATOR);
72     return filePath;
73 }
74 
ConvertToExtendResourceInfo(const std::string & bundleName,const InnerBundleInfo & innerBundleInfo,ExtendResourceInfo & extendResourceInfo)75 void ConvertToExtendResourceInfo(
76     const std::string &bundleName,
77     const InnerBundleInfo &innerBundleInfo,
78     ExtendResourceInfo &extendResourceInfo)
79 {
80     extendResourceInfo.moduleName = innerBundleInfo.GetCurModuleName();
81     extendResourceInfo.iconId = innerBundleInfo.GetIconId();
82     std::string path = BuildResourcePath(bundleName);
83     path.append(extendResourceInfo.moduleName).append(EXT_RESOURCE_FILE_SUFFIX);
84     extendResourceInfo.filePath = path;
85 }
86 }
ExtendResourceManagerHostImpl()87 ExtendResourceManagerHostImpl::ExtendResourceManagerHostImpl()
88 {
89     APP_LOGI("create ExtendResourceManagerHostImpl");
90 }
91 
~ExtendResourceManagerHostImpl()92 ExtendResourceManagerHostImpl::~ExtendResourceManagerHostImpl()
93 {
94     APP_LOGI("destroy ExtendResourceManagerHostImpl");
95 }
96 
AddExtResource(const std::string & bundleName,const std::vector<std::string> & filePaths)97 ErrCode ExtendResourceManagerHostImpl::AddExtResource(
98     const std::string &bundleName, const std::vector<std::string> &filePaths)
99 {
100     ErrCode ret = BeforeAddExtResource(bundleName, filePaths);
101     CHECK_RESULT(ret, "BeforeAddExtResource failed %{public}d");
102     ret = ProcessAddExtResource(bundleName, filePaths);
103     CHECK_RESULT(ret, "InnerEnableDynamicIcon failed %{public}d");
104     return ERR_OK;
105 }
106 
BeforeAddExtResource(const std::string & bundleName,const std::vector<std::string> & filePaths)107 ErrCode ExtendResourceManagerHostImpl::BeforeAddExtResource(
108     const std::string &bundleName, const std::vector<std::string> &filePaths)
109 {
110     if (bundleName.empty()) {
111         APP_LOGE("fail to AddExtResource due to bundleName is empty");
112         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
113     }
114 
115     if (filePaths.empty()) {
116         APP_LOGE("fail to AddExtResource due to filePaths is empty");
117         return ERR_EXT_RESOURCE_MANAGER_INVALID_PATH_FAILED;
118     }
119 
120     if (!BundlePermissionMgr::IsSystemApp()) {
121         APP_LOGE("Non-system app calling system api");
122         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
123     }
124 
125     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(
126         Constants::PERMISSION_INSTALL_BUNDLE)) {
127         APP_LOGE("verify permission failed");
128         return ERR_APPEXECFWK_PERMISSION_DENIED;
129     }
130 
131     for (const auto &filePath: filePaths) {
132         if (!CheckFileParam(filePath)) {
133             APP_LOGE("CheckFile failed");
134             return ERR_EXT_RESOURCE_MANAGER_INVALID_PATH_FAILED;
135         }
136     }
137 
138     return ERR_OK;
139 }
140 
CheckFileParam(const std::string & filePath)141 bool ExtendResourceManagerHostImpl::CheckFileParam(const std::string &filePath)
142 {
143     if (!IsValidPath(filePath)) {
144         APP_LOGE("CheckFile filePath(%{public}s) failed due to invalid path", filePath.c_str());
145         return false;
146     }
147     if (!BundleUtil::CheckFileType(filePath, EXT_RESOURCE_FILE_SUFFIX)) {
148         APP_LOGE("CheckFile filePath(%{public}s) failed due to suffix error", filePath.c_str());
149         return false;
150     }
151     if (!BundleUtil::StartWith(filePath, ServiceConstants::HAP_COPY_PATH)) {
152         APP_LOGE("CheckFile filePath(%{public}s) failed due to prefix error", filePath.c_str());
153         return false;
154     }
155     return true;
156 }
157 
ProcessAddExtResource(const std::string & bundleName,const std::vector<std::string> & filePaths)158 ErrCode ExtendResourceManagerHostImpl::ProcessAddExtResource(
159     const std::string &bundleName, const std::vector<std::string> &filePaths)
160 {
161     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
162     if (dataMgr == nullptr) {
163         APP_LOGE("Get dataMgr shared_ptr nullptr");
164         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
165     }
166     if (!dataMgr->IsBundleExist(bundleName)) {
167         APP_LOGE("-n %{public}s not exist, add ext resource failed", bundleName.c_str());
168         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
169     }
170     auto &mutex = dataMgr->GetBundleMutex(bundleName);
171     std::lock_guard lock {mutex};
172 
173     std::vector<std::string> newFilePaths;
174     ErrCode ret = CopyToTempDir(bundleName, filePaths, newFilePaths);
175     CHECK_RESULT(ret, "CopyToTempDir failed %{public}d");
176 
177     std::vector<ExtendResourceInfo> extendResourceInfos;
178     if (ParseExtendResourceFile(bundleName, newFilePaths, extendResourceInfos) != ERR_OK) {
179         APP_LOGE("parse %{public}s extendResource failed", bundleName.c_str());
180         RollBack(newFilePaths);
181         return ERR_EXT_RESOURCE_MANAGER_PARSE_FILE_FAILED;
182     }
183 
184     InnerSaveExtendResourceInfo(bundleName, newFilePaths, extendResourceInfos);
185     return ERR_OK;
186 }
187 
InnerSaveExtendResourceInfo(const std::string & bundleName,const std::vector<std::string> & filePaths,const std::vector<ExtendResourceInfo> & extendResourceInfos)188 void ExtendResourceManagerHostImpl::InnerSaveExtendResourceInfo(
189     const std::string &bundleName,
190     const std::vector<std::string> &filePaths,
191     const std::vector<ExtendResourceInfo> &extendResourceInfos)
192 {
193     ErrCode ret = ERR_OK;
194     std::vector<ExtendResourceInfo> newExtendResourceInfos;
195     for (uint32_t i = 0; i < filePaths.size(); ++i) {
196         ret = InstalldClient::GetInstance()->MoveFile(
197             filePaths[i], extendResourceInfos[i].filePath);
198         if (ret != ERR_OK) {
199             APP_LOGW("MoveFile %{public}s file failed %{public}d",
200                 extendResourceInfos[i].moduleName.c_str(), ret);
201             continue;
202         }
203 
204         newExtendResourceInfos.emplace_back(extendResourceInfos[i]);
205     }
206     UpateExtResourcesDb(bundleName, newExtendResourceInfos);
207 }
208 
ParseExtendResourceFile(const std::string & bundleName,const std::vector<std::string> & filePaths,std::vector<ExtendResourceInfo> & extendResourceInfos)209 ErrCode ExtendResourceManagerHostImpl::ParseExtendResourceFile(
210     const std::string &bundleName,
211     const std::vector<std::string> &filePaths,
212     std::vector<ExtendResourceInfo> &extendResourceInfos)
213 {
214     BundleInstallChecker bundleChecker;
215     std::vector<Security::Verify::HapVerifyResult> hapVerifyRes;
216     ErrCode ret = bundleChecker.CheckMultipleHapsSignInfo(filePaths, hapVerifyRes);
217     CHECK_RESULT(ret, "Check sign failed %{public}d");
218 
219     for (uint32_t i = 0; i < filePaths.size(); ++i) {
220         BundleParser bundleParser;
221         InnerBundleInfo innerBundleInfo;
222         ErrCode result = bundleParser.Parse(filePaths[i], innerBundleInfo);
223         if (result != ERR_OK) {
224             APP_LOGE("parse bundle info %{public}s failed, err %{public}d",
225                 filePaths[i].c_str(), result);
226             return result;
227         }
228 
229         ExtendResourceInfo extendResourceInfo;
230         ConvertToExtendResourceInfo(bundleName, innerBundleInfo, extendResourceInfo);
231         extendResourceInfos.emplace_back(extendResourceInfo);
232     }
233 
234     return ERR_OK;
235 }
236 
MkdirIfNotExist(const std::string & dir)237 ErrCode ExtendResourceManagerHostImpl::MkdirIfNotExist(const std::string &dir)
238 {
239     bool isDirExist = false;
240     ErrCode result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExist);
241     if (result != ERR_OK) {
242         APP_LOGE("Check if dir exist failed %{public}d", result);
243         return result;
244     }
245     if (!isDirExist) {
246         result = InstalldClient::GetInstance()->CreateBundleDir(dir);
247         if (result != ERR_OK) {
248             APP_LOGE("Create dir failed %{public}d", result);
249             return result;
250         }
251     }
252     return result;
253 }
254 
CopyToTempDir(const std::string & bundleName,const std::vector<std::string> & oldFilePaths,std::vector<std::string> & newFilePaths)255 ErrCode ExtendResourceManagerHostImpl::CopyToTempDir(const std::string &bundleName,
256     const std::vector<std::string> &oldFilePaths, std::vector<std::string> &newFilePaths)
257 {
258     for (const auto &oldFile : oldFilePaths) {
259         std::string tempFile = BuildResourcePath(bundleName);
260         ErrCode ret = MkdirIfNotExist(tempFile);
261         if (ret != ERR_OK) {
262             APP_LOGE("mkdir fileDir %{public}s failed %{public}d", tempFile.c_str(), ret);
263             RollBack(newFilePaths);
264             return ret;
265         }
266         tempFile.append(GetFileName(oldFile));
267         ret = InstalldClient::GetInstance()->MoveFile(oldFile, tempFile);
268         if (ret != ERR_OK) {
269             APP_LOGE("MoveFile file %{public}s failed %{public}d", tempFile.c_str(), ret);
270             RollBack(newFilePaths);
271             return ret;
272         }
273         newFilePaths.emplace_back(tempFile);
274     }
275     return ERR_OK;
276 }
277 
GetInnerBundleInfo(const std::string & bundleName,InnerBundleInfo & info)278 bool ExtendResourceManagerHostImpl::GetInnerBundleInfo(
279     const std::string &bundleName, InnerBundleInfo &info)
280 {
281     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
282     if (dataMgr == nullptr) {
283         APP_LOGE("Get dataMgr shared_ptr nullptr");
284         return false;
285     }
286     return dataMgr->FetchInnerBundleInfo(bundleName, info);
287 }
288 
UpateExtResourcesDb(const std::string & bundleName,const std::vector<ExtendResourceInfo> & extendResourceInfos)289 bool ExtendResourceManagerHostImpl::UpateExtResourcesDb(const std::string &bundleName,
290     const std::vector<ExtendResourceInfo> &extendResourceInfos)
291 {
292     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
293     if (dataMgr == nullptr) {
294         APP_LOGE("Get dataMgr shared_ptr nullptr");
295         return false;
296     }
297     return dataMgr->UpateExtResources(bundleName, extendResourceInfos);
298 }
299 
RemoveExtResourcesDb(const std::string & bundleName,const std::vector<std::string> & moduleNames)300 bool ExtendResourceManagerHostImpl::RemoveExtResourcesDb(const std::string &bundleName,
301     const std::vector<std::string> &moduleNames)
302 {
303     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
304     if (dataMgr == nullptr) {
305         APP_LOGE("Get dataMgr shared_ptr nullptr");
306         return false;
307     }
308     return dataMgr->RemoveExtResources(bundleName, moduleNames);
309 }
310 
RollBack(const std::vector<std::string> & filePaths)311 void ExtendResourceManagerHostImpl::RollBack(const std::vector<std::string> &filePaths)
312 {
313     for (const auto &filePath : filePaths) {
314         ErrCode result = InstalldClient::GetInstance()->RemoveDir(filePath);
315         if (result != ERR_OK) {
316             APP_LOGE("Remove failed %{public}s", filePath.c_str());
317         }
318     }
319 }
320 
RemoveExtResource(const std::string & bundleName,const std::vector<std::string> & moduleNames)321 ErrCode ExtendResourceManagerHostImpl::RemoveExtResource(
322     const std::string &bundleName, const std::vector<std::string> &moduleNames)
323 {
324     if (bundleName.empty()) {
325         APP_LOGE("fail to RemoveExtResource due to bundleName is empty");
326         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
327     }
328 
329     if (moduleNames.empty()) {
330         APP_LOGE("fail to RemoveExtResource due to moduleName is empty");
331         return ERR_EXT_RESOURCE_MANAGER_REMOVE_EXT_RESOURCE_FAILED;
332     }
333 
334     if (!BundlePermissionMgr::IsSystemApp()) {
335         APP_LOGE("Non-system app calling system api");
336         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
337     }
338 
339     if (!BundlePermissionMgr::VerifyCallingPermissionsForAll({
340         Constants::PERMISSION_INSTALL_BUNDLE, ServiceConstants::PERMISSION_UNINSTALL_BUNDLE})) {
341         APP_LOGE("verify permission failed");
342         return ERR_APPEXECFWK_PERMISSION_DENIED;
343     }
344 
345     std::vector<ExtendResourceInfo> extendResourceInfos;
346     ErrCode ret = CheckModuleExist(bundleName, moduleNames, extendResourceInfos);
347     CHECK_RESULT(ret, "Check mpdule exist failed %{public}d");
348     InnerRemoveExtendResources(bundleName, moduleNames, extendResourceInfos);
349     return ERR_OK;
350 }
351 
InnerRemoveExtendResources(const std::string & bundleName,const std::vector<std::string> & moduleNames,std::vector<ExtendResourceInfo> & extResourceInfos)352 void ExtendResourceManagerHostImpl::InnerRemoveExtendResources(
353     const std::string &bundleName, const std::vector<std::string> &moduleNames,
354     std::vector<ExtendResourceInfo> &extResourceInfos)
355 {
356     for (const auto &extResourceInfo : extResourceInfos) {
357         ErrCode result = InstalldClient::GetInstance()->RemoveDir(extResourceInfo.filePath);
358         if (result != ERR_OK) {
359             APP_LOGE("Remove failed %{public}s", extResourceInfo.filePath.c_str());
360         }
361     }
362     RemoveExtResourcesDb(bundleName, moduleNames);
363 }
364 
CheckModuleExist(const std::string & bundleName,const std::vector<std::string> & moduleNames,std::vector<ExtendResourceInfo> & collectorExtResourceInfos)365 ErrCode ExtendResourceManagerHostImpl::CheckModuleExist(
366     const std::string &bundleName, const std::vector<std::string> &moduleNames,
367     std::vector<ExtendResourceInfo> &collectorExtResourceInfos)
368 {
369     InnerBundleInfo info;
370     if (!GetInnerBundleInfo(bundleName, info)) {
371         APP_LOGE("GetInnerBundleInfo failed %{public}s", bundleName.c_str());
372         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
373     }
374 
375     std::map<std::string, ExtendResourceInfo> extendResourceInfos = info.GetExtendResourceInfos();
376     for (const auto &moduleName : moduleNames) {
377         auto iter = extendResourceInfos.find(moduleName);
378         if (iter == extendResourceInfos.end()) {
379             APP_LOGE("Module not exist %{public}s", moduleName.c_str());
380             return ERR_EXT_RESOURCE_MANAGER_REMOVE_EXT_RESOURCE_FAILED;
381         }
382 
383         collectorExtResourceInfos.emplace_back(iter->second);
384     }
385     return ERR_OK;
386 }
387 
GetExtResource(const std::string & bundleName,std::vector<std::string> & moduleNames)388 ErrCode ExtendResourceManagerHostImpl::GetExtResource(
389     const std::string &bundleName, std::vector<std::string> &moduleNames)
390 {
391     if (bundleName.empty()) {
392         APP_LOGE("fail to GetExtResource due to param is empty");
393         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
394     }
395 
396     if (!BundlePermissionMgr::IsSystemApp()) {
397         APP_LOGE("Non-system app calling system api");
398         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
399     }
400 
401     if (!BundlePermissionMgr::VerifyCallingPermissionsForAll({
402         Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED, Constants::PERMISSION_GET_BUNDLE_INFO})) {
403         APP_LOGE("verify permission failed");
404         return ERR_APPEXECFWK_PERMISSION_DENIED;
405     }
406 
407     InnerBundleInfo info;
408     if (!GetInnerBundleInfo(bundleName, info)) {
409         APP_LOGE("GetInnerBundleInfo failed %{public}s", bundleName.c_str());
410         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
411     }
412 
413     std::map<std::string, ExtendResourceInfo> extendResourceInfos = info.GetExtendResourceInfos();
414     if (extendResourceInfos.empty()) {
415         APP_LOGE("%{public}s no extend Resources", bundleName.c_str());
416         return ERR_EXT_RESOURCE_MANAGER_GET_EXT_RESOURCE_FAILED;
417     }
418 
419     for (const auto &extendResourceInfo : extendResourceInfos) {
420         moduleNames.emplace_back(extendResourceInfo.first);
421     }
422 
423     return ERR_OK;
424 }
425 
EnableDynamicIcon(const std::string & bundleName,const std::string & moduleName)426 ErrCode ExtendResourceManagerHostImpl::EnableDynamicIcon(
427     const std::string &bundleName, const std::string &moduleName)
428 {
429     return EnableDynamicIcon(bundleName, moduleName, Constants::UNSPECIFIED_USERID, Constants::DEFAULT_APP_INDEX);
430 }
431 
EnableDynamicIcon(const std::string & bundleName,const std::string & moduleName,const int32_t userId,const int32_t appIndex)432 ErrCode ExtendResourceManagerHostImpl::EnableDynamicIcon(
433     const std::string &bundleName, const std::string &moduleName, const int32_t userId, const int32_t appIndex)
434 {
435     APP_LOGI("EnableDynamicIcon %{public}s, %{public}s, %{public}d, %{public}d",
436         bundleName.c_str(), moduleName.c_str(), userId, appIndex);
437     if (bundleName.empty()) {
438         APP_LOGE("fail to EnableDynamicIcon due to bundleName is empty");
439         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
440     }
441 
442     if (moduleName.empty()) {
443         APP_LOGE("fail to EnableDynamicIcon due to moduleName is empty");
444         return ERR_BUNDLE_MANAGER_MODULE_NOT_EXIST;
445     }
446 
447     if (!BundlePermissionMgr::IsSystemApp()) {
448         APP_LOGE("Non-system app calling system api");
449         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
450     }
451 
452     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_ACCESS_DYNAMIC_ICON)) {
453         APP_LOGE("verify permission failed");
454         return ERR_APPEXECFWK_PERMISSION_DENIED;
455     }
456     if ((userId != Constants::UNSPECIFIED_USERID)) {
457         if (!CheckAcrossUserPermission(userId)) {
458             APP_LOGE("verify permission across local account failed");
459             return ERR_APPEXECFWK_PERMISSION_DENIED;
460         }
461     }
462 
463     ExtendResourceInfo extendResourceInfo;
464     ErrCode ret = GetExtendResourceInfo(bundleName, moduleName, extendResourceInfo, userId, appIndex);
465     CHECK_RESULT(ret, "GetExtendResourceInfo failed %{public}d");
466     if (!CheckWhetherDynamicIconNeedProcess(bundleName, userId)) {
467         APP_LOGE("%{public}s enable failed due to existing custom themes", bundleName.c_str());
468         return ERR_EXT_RESOURCE_MANAGER_ENABLE_DYNAMIC_ICON_FAILED_DUE_TO_EXISTING_CUSTOM_THEMES;
469     }
470     if (!ParseBundleResource(bundleName, extendResourceInfo, userId, appIndex)) {
471         APP_LOGE("%{public}s no extend Resources", bundleName.c_str());
472         return ERR_EXT_RESOURCE_MANAGER_ENABLE_DYNAMIC_ICON_FAILED;
473     }
474 
475     SaveCurDynamicIcon(bundleName, moduleName, userId, appIndex);
476     SendBroadcast(bundleName, true, userId, appIndex);
477     return ERR_OK;
478 }
479 
SaveCurDynamicIcon(const std::string & bundleName,const std::string & moduleName,const int32_t userId,const int32_t appIndex)480 void ExtendResourceManagerHostImpl::SaveCurDynamicIcon(
481     const std::string &bundleName, const std::string &moduleName, const int32_t userId, const int32_t appIndex)
482 {
483     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
484     if (dataMgr == nullptr) {
485         APP_LOGE("Get dataMgr shared_ptr nullptr");
486         return;
487     }
488 
489     dataMgr->UpateCurDynamicIconModule(bundleName, moduleName, userId, appIndex);
490 }
491 
SendBroadcast(const std::string & bundleName,bool isEnableDynamicIcon,const int32_t userId,const int32_t appIndex)492 void ExtendResourceManagerHostImpl::SendBroadcast(
493     const std::string &bundleName, bool isEnableDynamicIcon,
494     const int32_t userId, const int32_t appIndex)
495 {
496     std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
497     commonEventMgr->NotifyDynamicIconEvent(bundleName, isEnableDynamicIcon, userId, appIndex);
498 }
499 
ParseBundleResource(const std::string & bundleName,const ExtendResourceInfo & extendResourceInfo,const int32_t userId,const int32_t appIndex)500 bool ExtendResourceManagerHostImpl::ParseBundleResource(
501     const std::string &bundleName, const ExtendResourceInfo &extendResourceInfo,
502     const int32_t userId, const int32_t appIndex)
503 {
504     APP_LOGI("ParseBundleResource %{public}s", bundleName.c_str());
505 #ifdef BUNDLE_FRAMEWORK_BUNDLE_RESOURCE
506     ResourceInfo info;
507     info.bundleName_ = bundleName;
508     info.iconId_ = extendResourceInfo.iconId;
509     info.appIndex_ = appIndex;
510     BundleResourceParser bundleResourceParser;
511     if (!bundleResourceParser.ParseIconResourceByPath(extendResourceInfo.filePath,
512         extendResourceInfo.iconId, info)) {
513         APP_LOGW("ParseIconResourceByPath failed, bundleName:%{public}s", bundleName.c_str());
514         return false;
515     }
516     if (info.icon_.empty()) {
517         APP_LOGE("icon empty %{public}s", bundleName.c_str());
518         return false;
519     }
520     auto manager = DelayedSingleton<BundleResourceManager>::GetInstance();
521     if (manager == nullptr) {
522         APP_LOGE("failed, manager is nullptr");
523         return false;
524     }
525     if (!manager->AddDynamicIconResource(bundleName, userId, appIndex, info)) {
526         APP_LOGE("UpdateBundleIcon failed, bundleName:%{public}s", bundleName.c_str());
527         return false;
528     }
529     return true;
530 #else
531     APP_LOGI("bundle resource not support");
532     return false;
533 #endif
534 }
535 
GetExtendResourceInfo(const std::string & bundleName,const std::string & moduleName,ExtendResourceInfo & extendResourceInfo,const int32_t userId,const int32_t appIndex)536 ErrCode ExtendResourceManagerHostImpl::GetExtendResourceInfo(const std::string &bundleName,
537     const std::string &moduleName, ExtendResourceInfo &extendResourceInfo,
538     const int32_t userId, const int32_t appIndex)
539 {
540     InnerBundleInfo info;
541     if (!GetInnerBundleInfo(bundleName, info)) {
542         APP_LOGE("GetInnerBundleInfo failed %{public}s", bundleName.c_str());
543         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
544     }
545     std::map<std::string, ExtendResourceInfo> extendResourceInfos = info.GetExtendResourceInfos();
546     if (extendResourceInfos.empty()) {
547         APP_LOGE("%{public}s no extend Resources", bundleName.c_str());
548         return ERR_BUNDLE_MANAGER_MODULE_NOT_EXIST;
549     }
550     auto iter = extendResourceInfos.find(moduleName);
551     if (iter == extendResourceInfos.end()) {
552         APP_LOGE("%{public}s no %{public}s extend Resources", bundleName.c_str(), moduleName.c_str());
553         return ERR_BUNDLE_MANAGER_MODULE_NOT_EXIST;
554     }
555     ErrCode ret = CheckParamInvalid(info, userId, appIndex);
556     CHECK_RESULT(ret, "check user or appIndex failed %{public}d");
557     extendResourceInfo = iter->second;
558     return ERR_OK;
559 }
560 
DisableDynamicIcon(const std::string & bundleName)561 ErrCode ExtendResourceManagerHostImpl::DisableDynamicIcon(const std::string &bundleName)
562 {
563     return DisableDynamicIcon(bundleName, Constants::UNSPECIFIED_USERID, Constants::DEFAULT_APP_INDEX);
564 }
565 
DisableDynamicIcon(const std::string & bundleName,const int32_t userId,const int32_t appIndex)566 ErrCode ExtendResourceManagerHostImpl::DisableDynamicIcon(const std::string &bundleName,
567     const int32_t userId, const int32_t appIndex)
568 {
569     APP_LOGI("DisableDynamicIcon %{public}s userId %{public}d appIndex %{public}d", bundleName.c_str(),
570         userId, appIndex);
571     if (bundleName.empty()) {
572         APP_LOGE("fail to DisableDynamicIcon due to param is empty");
573         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
574     }
575 
576     if (!BundlePermissionMgr::IsSystemApp()) {
577         APP_LOGE("Non-system app calling system api");
578         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
579     }
580 
581     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(
582         Constants::PERMISSION_ACCESS_DYNAMIC_ICON)) {
583         APP_LOGE("verify permission failed");
584         return ERR_APPEXECFWK_PERMISSION_DENIED;
585     }
586 
587     if ((userId != Constants::UNSPECIFIED_USERID)) {
588         if (!CheckAcrossUserPermission(userId)) {
589             APP_LOGE("verify permission across local account failed");
590             return ERR_APPEXECFWK_PERMISSION_DENIED;
591         }
592     }
593 
594     InnerBundleInfo info;
595     if (!GetInnerBundleInfo(bundleName, info)) {
596         APP_LOGE("GetInnerBundleInfo failed %{public}s", bundleName.c_str());
597         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
598     }
599     ErrCode ret = CheckParamInvalid(info, userId, appIndex);
600     CHECK_RESULT(ret, "check user or appIndex failed %{public}d");
601 
602     std::string curDynamicModule = info.GetCurDynamicIconModule(userId, appIndex);
603     std::vector<DynamicIconInfo> dynamicIconInfos;
604     if (curDynamicModule.empty() && (userId == Constants::UNSPECIFIED_USERID)) {
605         info.GetAllDynamicIconInfo(userId, dynamicIconInfos);
606     }
607     if (curDynamicModule.empty() && dynamicIconInfos.empty()) {
608         APP_LOGE("%{public}s -u %{public}d no enabled dynamic icon", bundleName.c_str(), userId);
609         return ERR_EXT_RESOURCE_MANAGER_DISABLE_DYNAMIC_ICON_FAILED;
610     }
611 
612     SaveCurDynamicIcon(bundleName, "", userId, appIndex);
613     (void)ResetBundleResourceIcon(bundleName, userId, appIndex);
614     SendBroadcast(bundleName, false, userId, appIndex);
615     return ERR_OK;
616 }
617 
ResetBundleResourceIcon(const std::string & bundleName,const int32_t userId,const int32_t appIndex)618 bool ExtendResourceManagerHostImpl::ResetBundleResourceIcon(const std::string &bundleName,
619     const int32_t userId, const int32_t appIndex)
620 {
621 #ifdef BUNDLE_FRAMEWORK_BUNDLE_RESOURCE
622     APP_LOGI("ResetBundleResourceIcon %{public}s userId %{public}d appIndex %{public}d", bundleName.c_str(),
623         userId, appIndex);
624     auto manager = DelayedSingleton<BundleResourceManager>::GetInstance();
625     if (manager == nullptr) {
626         APP_LOGE("failed, manager is nullptr");
627         return false;
628     }
629     if (!manager->DeleteDynamicIconResource(bundleName, userId, appIndex)) {
630         APP_LOGE("%{public}s userId %{public}d appIndex %{public}d add resource failed", bundleName.c_str(),
631             userId, appIndex);
632         return false;
633     }
634     return true;
635 #else
636     return false;
637 #endif
638 }
639 
GetDynamicIcon(const std::string & bundleName,std::string & moduleName)640 ErrCode ExtendResourceManagerHostImpl::GetDynamicIcon(
641     const std::string &bundleName, std::string &moduleName)
642 {
643     return GetDynamicIcon(bundleName, Constants::UNSPECIFIED_USERID, Constants::DEFAULT_APP_INDEX, moduleName);
644 }
645 
GetDynamicIcon(const std::string & bundleName,const int32_t userId,const int32_t appIndex,std::string & moudleName)646 ErrCode ExtendResourceManagerHostImpl::GetDynamicIcon(
647     const std::string &bundleName, const int32_t userId, const int32_t appIndex, std::string &moudleName)
648 {
649     if (bundleName.empty()) {
650         APP_LOGE("fail to GetDynamicIcon due to param is empty");
651         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
652     }
653 
654     if (!BundlePermissionMgr::IsSystemApp()) {
655         APP_LOGE("Non-system app calling system api");
656         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
657     }
658 
659     if (!BundlePermissionMgr::VerifyCallingPermissionsForAll({
660         Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED, Constants::PERMISSION_GET_BUNDLE_INFO})) {
661         APP_LOGE("verify permission failed");
662         return ERR_APPEXECFWK_PERMISSION_DENIED;
663     }
664 
665     InnerBundleInfo info;
666     if (!GetInnerBundleInfo(bundleName, info)) {
667         APP_LOGE("GetInnerBundleInfo failed %{public}s", bundleName.c_str());
668         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
669     }
670     ErrCode ret = CheckParamInvalid(info, userId, appIndex);
671     CHECK_RESULT(ret, "check user or appIndex failed %{public}d");
672 
673     std::string curDynamicModule = info.GetCurDynamicIconModule(userId, appIndex);
674     if (curDynamicModule.empty() && (userId == Constants::UNSPECIFIED_USERID)) {
675         int32_t realUserId = BundleUtil::GetUserIdByCallingUid();
676         realUserId = (realUserId == Constants::DEFAULT_USERID) ? AccountHelper::GetCurrentActiveUserId() : realUserId;
677         curDynamicModule = info.GetCurDynamicIconModule(realUserId, appIndex);
678     }
679     if (curDynamicModule.empty()) {
680         APP_LOGE("%{public}s no enabled dynamic icon", bundleName.c_str());
681         return ERR_EXT_RESOURCE_MANAGER_GET_DYNAMIC_ICON_FAILED;
682     }
683 
684     moudleName = curDynamicModule;
685     return ERR_OK;
686 }
687 
CreateFd(const std::string & fileName,int32_t & fd,std::string & path)688 ErrCode ExtendResourceManagerHostImpl::CreateFd(
689     const std::string &fileName, int32_t &fd, std::string &path)
690 {
691     if (fileName.empty()) {
692         APP_LOGE("fail to CreateFd due to param is empty");
693         return ERR_EXT_RESOURCE_MANAGER_CREATE_FD_FAILED;
694     }
695     if (!BundlePermissionMgr::IsSystemApp()) {
696         APP_LOGE("Non-system app calling system api");
697         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
698     }
699     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(
700         Constants::PERMISSION_INSTALL_BUNDLE)) {
701         APP_LOGE("verify permission failed");
702         return ERR_APPEXECFWK_PERMISSION_DENIED;
703     }
704     if (!BundleUtil::CheckFileType(fileName, EXT_RESOURCE_FILE_SUFFIX)) {
705         APP_LOGE("not hsp file");
706         return ERR_EXT_RESOURCE_MANAGER_CREATE_FD_FAILED;
707     }
708     if (!IsFileNameValid(fileName)) {
709         APP_LOGE("invalid fileName");
710         return ERR_EXT_RESOURCE_MANAGER_CREATE_FD_FAILED;
711     }
712     std::string tmpDir = BundleUtil::CreateInstallTempDir(
713         ++id_, DirType::EXT_RESOURCE_FILE_DIR);
714     if (tmpDir.empty()) {
715         APP_LOGE("create tmp dir failed");
716         return ERR_EXT_RESOURCE_MANAGER_CREATE_FD_FAILED;
717     }
718     path = tmpDir + fileName;
719     if ((fd = BundleUtil::CreateFileDescriptor(path, 0)) < 0) {
720         APP_LOGE("create file descriptor failed");
721         BundleUtil::DeleteDir(tmpDir);
722         return ERR_EXT_RESOURCE_MANAGER_CREATE_FD_FAILED;
723     }
724     return ERR_OK;
725 }
726 
CheckParamInvalid(const InnerBundleInfo & bundleInfo,const int32_t userId,const int32_t appIndex)727 ErrCode ExtendResourceManagerHostImpl::CheckParamInvalid(const InnerBundleInfo &bundleInfo,
728     const int32_t userId, const int32_t appIndex)
729 {
730     if ((userId == Constants::UNSPECIFIED_USERID) && (appIndex == Constants::DEFAULT_APP_INDEX)) {
731         return ERR_OK;
732     }
733     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
734     if (dataMgr == nullptr) {
735         APP_LOGE("Get dataMgr shared_ptr nullptr");
736         return ERR_APPEXECFWK_NULL_PTR;
737     }
738     if (!dataMgr->HasUserId(userId)) {
739         APP_LOGE("userId %{public}d not exist", userId);
740         return ERR_BUNDLE_MANAGER_INVALID_USER_ID;
741     }
742     InnerBundleUserInfo userInfo;
743     if (!bundleInfo.GetInnerBundleUserInfo(userId, userInfo)) {
744         APP_LOGE("bundle %{public}s not exist in userId %{public}d", bundleInfo.GetBundleName().c_str(), userId);
745         return ERR_BUNDLE_MANAGER_BUNDLE_NOT_EXIST;
746     }
747     if (appIndex == 0) {
748         return ERR_OK;
749     }
750     std::string cloneInfoKey = InnerBundleUserInfo::AppIndexToKey(appIndex);
751     if (userInfo.cloneInfos.find(cloneInfoKey) == userInfo.cloneInfos.end()) {
752         APP_LOGE("bundle %{public}s not exist in userId %{public}d appIndex %{public}d",
753             bundleInfo.GetBundleName().c_str(), userId, appIndex);
754         return ERR_APPEXECFWK_APP_INDEX_OUT_OF_RANGE;
755     }
756     return ERR_OK;
757 }
758 
GetAllDynamicIconInfo(std::vector<DynamicIconInfo> & dynamicInfos)759 ErrCode ExtendResourceManagerHostImpl::GetAllDynamicIconInfo(std::vector<DynamicIconInfo> &dynamicInfos)
760 {
761     return GetAllDynamicIconInfo(Constants::UNSPECIFIED_USERID, dynamicInfos);
762 }
763 
GetAllDynamicIconInfo(const int32_t userId,std::vector<DynamicIconInfo> & dynamicInfos)764 ErrCode ExtendResourceManagerHostImpl::GetAllDynamicIconInfo(
765     const int32_t userId, std::vector<DynamicIconInfo> &dynamicInfos)
766 {
767     APP_LOGI("get all dynamic info userId %{public}d", userId);
768     if (!BundlePermissionMgr::IsSystemApp()) {
769         APP_LOGE("Non-system app calling system api");
770         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
771     }
772     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED)) {
773         APP_LOGE("verify permission failed");
774         return ERR_APPEXECFWK_PERMISSION_DENIED;
775     }
776     if (!CheckAcrossUserPermission(userId)) {
777         APP_LOGE("verify permission across local account failed");
778         return ERR_APPEXECFWK_PERMISSION_DENIED;
779     }
780     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
781     if (dataMgr == nullptr) {
782         APP_LOGE("Get dataMgr shared_ptr nullptr");
783         return ERR_APPEXECFWK_NULL_PTR;
784     }
785     auto ret = dataMgr->GetAllDynamicIconInfo(userId, dynamicInfos);
786     if ((ret == ERR_OK) && dynamicInfos.empty()) {
787         ret = ERR_EXT_RESOURCE_MANAGER_GET_DYNAMIC_ICON_FAILED;
788     }
789     if (ret != ERR_OK) {
790         APP_LOGE("-u %{public}d get all dynamic info failed ret %{public}d", userId, ret);
791     }
792     return ret;
793 }
794 
GetDynamicIconInfo(const std::string & bundleName,std::vector<DynamicIconInfo> & dynamicInfos)795 ErrCode ExtendResourceManagerHostImpl::GetDynamicIconInfo(const std::string &bundleName,
796     std::vector<DynamicIconInfo> &dynamicInfos)
797 {
798     APP_LOGI("get dynamic info -n %{public}s", bundleName.c_str());
799     if (!BundlePermissionMgr::IsSystemApp()) {
800         APP_LOGE("Non-system app calling system api");
801         return ERR_BUNDLE_MANAGER_SYSTEM_API_DENIED;
802     }
803     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_GET_BUNDLE_INFO_PRIVILEGED) ||
804         !BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_BMS_INTERACT_ACROSS_LOCAL_ACCOUNTS)) {
805         APP_LOGE("verify permission failed");
806         return ERR_APPEXECFWK_PERMISSION_DENIED;
807     }
808     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
809     if (dataMgr == nullptr) {
810         APP_LOGE("Get dataMgr shared_ptr nullptr");
811         return ERR_APPEXECFWK_NULL_PTR;
812     }
813     auto ret = dataMgr->GetDynamicIconInfo(bundleName, dynamicInfos);
814     if ((ret == ERR_OK) && dynamicInfos.empty()) {
815         ret = ERR_EXT_RESOURCE_MANAGER_GET_DYNAMIC_ICON_FAILED;
816     }
817     if (ret != ERR_OK) {
818         APP_LOGE("-n %{public}s get dynamic info failed ret %{public}d", bundleName.c_str(), ret);
819     }
820     return ret;
821 }
822 
IsNeedUpdateBundleResourceInfo(const std::string & bundleName,const int32_t userId)823 bool ExtendResourceManagerHostImpl::IsNeedUpdateBundleResourceInfo(
824     const std::string &bundleName, const int32_t userId)
825 {
826     if (userId == Constants::DEFAULT_USERID) {
827         return true;
828     }
829     int32_t currentUserId = AccountHelper::GetCurrentActiveUserId();
830     if ((currentUserId <= 0)) {
831         currentUserId = Constants::START_USERID;
832     }
833     if (currentUserId == userId) {
834         return true;
835     }
836 
837     auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
838     if (dataMgr == nullptr) {
839         APP_LOGE("Get dataMgr shared_ptr nullptr");
840         return false;
841     }
842     std::vector<int32_t> userIds = dataMgr->GetUserIds(bundleName);
843     // bundleName exist in current userId, need check userId
844     if (std::find(userIds.begin(), userIds.end(), currentUserId) != userIds.end()) {
845         APP_LOGW("currentUserId %{public}d userId %{public}d not same", currentUserId, userId);
846         return false;
847     }
848     APP_LOGI("bundle %{public}s userId %{public}d need update bundle resource", bundleName.c_str(), userId);
849     return true;
850 }
851 
CheckAcrossUserPermission(const int32_t userId)852 bool ExtendResourceManagerHostImpl::CheckAcrossUserPermission(const int32_t userId)
853 {
854     // sa no need to check across user permission
855     if (BundlePermissionMgr::IsNativeTokenType()) {
856         return true;
857     }
858     if (userId == BundleUtil::GetUserIdByCallingUid()) {
859         return true;
860     }
861     if (!BundlePermissionMgr::VerifyCallingPermissionForAll(Constants::PERMISSION_BMS_INTERACT_ACROSS_LOCAL_ACCOUNTS)) {
862         APP_LOGE("verify permission across local account failed");
863         return false;
864     }
865     return true;
866 }
867 
CheckWhetherDynamicIconNeedProcess(const std::string & bundleName,const int32_t userId)868 bool ExtendResourceManagerHostImpl::CheckWhetherDynamicIconNeedProcess(
869     const std::string &bundleName, const int32_t userId)
870 {
871 #ifdef BUNDLE_FRAMEWORK_BUNDLE_RESOURCE
872     int32_t currentUserId = userId;
873     if (currentUserId == Constants::UNSPECIFIED_USERID) {
874         if (BundlePermissionMgr::IsNativeTokenType()) {
875             currentUserId = AccountHelper::GetCurrentActiveUserId();
876         } else {
877             currentUserId = BundleUtil::GetUserIdByCallingUid();
878         }
879     }
880     bool isOnlineTheme = false;
881     if (BundleResourceProcess::CheckThemeType(bundleName, currentUserId, isOnlineTheme) && isOnlineTheme) {
882         APP_LOGW("online theme first, no need to process -n %{public}s -u %{public}d dynamic icon",
883             bundleName.c_str(), currentUserId);
884         return false;
885     }
886     return true;
887 #else
888     return true;
889 #endif
890 }
891 } // AppExecFwk
892 } // namespace OHOS
893