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