1 /*
2 * Copyright (c) 2023-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 "bundle_resource_manager.h"
17
18 #include "account_helper.h"
19 #include "bms_extension_client.h"
20 #include "bundle_common_event_mgr.h"
21 #include "bundle_permission_mgr.h"
22 #include "bundle_util.h"
23 #include "bundle_resource_parser.h"
24 #include "bundle_resource_process.h"
25 #include "bundle_resource_theme_process.h"
26 #include "bundle_mgr_service.h"
27 #include "directory_ex.h"
28 #include "event_report.h"
29 #include "hitrace_meter.h"
30 #include "thread_pool.h"
31
32 namespace OHOS {
33 namespace AppExecFwk {
34 namespace {
35 constexpr const char* GLOBAL_RESOURCE_BUNDLE_NAME = "ohos.global.systemres";
36 constexpr int8_t MAX_TASK_NUMBER = 2;
37 constexpr const char* THREAD_POOL_NAME = "BundleResourceThreadPool";
38 constexpr int8_t CHECK_INTERVAL = 30; // 30ms
39 constexpr const char* FOUNDATION_PROCESS_NAME = "foundation";
40 constexpr int8_t SCENE_ID_UPDATE_RESOURCE = 1 << 1;
41 constexpr const char* INNER_UNDER_LINE = "_";
42 constexpr const char* TASK_NAME = "ReleaseResourceTask";
43 constexpr uint64_t DELAY_TIME_MILLI_SECONDS = 3 * 60 * 1000; // 3mins
44 constexpr const char* CONTACTS_BUNDLE_NAME = "com.ohos.contacts";
45 using Want = OHOS::AAFwk::Want;
46 }
47 std::mutex BundleResourceManager::g_sysResMutex;
48 std::shared_ptr<Global::Resource::ResourceManager> BundleResourceManager::g_resMgr = nullptr;
49
BundleResourceManager()50 BundleResourceManager::BundleResourceManager()
51 {
52 bundleResourceRdb_ = std::make_shared<BundleResourceRdb>();
53 bundleResourceIconRdb_ = std::make_shared<BundleResourceIconRdb>();
54 delayedTaskMgr_ = std::make_shared<SingleDelayedTaskMgr>(TASK_NAME, DELAY_TIME_MILLI_SECONDS);
55 }
56
~BundleResourceManager()57 BundleResourceManager::~BundleResourceManager()
58 {
59 }
60
DeleteNotExistResourceInfo(const std::string & bundleName,const int32_t appIndex,const std::vector<ResourceInfo> & resourceInfos)61 void BundleResourceManager::DeleteNotExistResourceInfo(
62 const std::string &bundleName, const int32_t appIndex, const std::vector<ResourceInfo> &resourceInfos)
63 {
64 // get current rdb resource
65 std::vector<std::string> existResourceName;
66 if (bundleResourceRdb_->GetResourceNameByBundleName(bundleName, appIndex, existResourceName) &&
67 !existResourceName.empty()) {
68 for (const auto &key : existResourceName) {
69 auto it = std::find_if(resourceInfos.begin(), resourceInfos.end(),
70 [&key](const ResourceInfo &info) {
71 return info.GetKey() == key;
72 });
73 if (it == resourceInfos.end()) {
74 bundleResourceRdb_->DeleteResourceInfo(key);
75 }
76 }
77 }
78 }
79
DeleteAllResourceInfo()80 bool BundleResourceManager::DeleteAllResourceInfo()
81 {
82 return bundleResourceRdb_->DeleteAllResourceInfo();
83 }
84
InnerProcessResourceInfoBySystemLanguageChanged(std::map<std::string,std::vector<ResourceInfo>> & resourceInfosMap)85 void BundleResourceManager::InnerProcessResourceInfoBySystemLanguageChanged(
86 std::map<std::string, std::vector<ResourceInfo>> &resourceInfosMap)
87 {
88 for (auto iter = resourceInfosMap.begin(); iter != resourceInfosMap.end(); ++iter) {
89 for (auto &resourceInfo : iter->second) {
90 resourceInfo.iconNeedParse_ = false;
91 }
92 }
93 }
94
DeleteNotExistResourceInfo(const std::map<std::string,std::vector<ResourceInfo>> & resourceInfosMap,const std::vector<std::string> & existResourceNames)95 void BundleResourceManager::DeleteNotExistResourceInfo(
96 const std::map<std::string, std::vector<ResourceInfo>> &resourceInfosMap,
97 const std::vector<std::string> &existResourceNames)
98 {
99 // delete not exist resource
100 for (const auto &name : existResourceNames) {
101 if (resourceInfosMap.find(name) == resourceInfosMap.end()) {
102 ResourceInfo resourceInfo;
103 resourceInfo.ParseKey(name);
104 // main bundle not exist
105 if (resourceInfo.appIndex_ == 0) {
106 DeleteResourceInfo(name);
107 continue;
108 }
109 auto iter = resourceInfosMap.find(resourceInfo.bundleName_);
110 // main bundle not exist
111 if ((iter == resourceInfosMap.end()) || (iter->second.empty())) {
112 DeleteResourceInfo(name);
113 continue;
114 }
115 // clone bundle appIndex not exist
116 if (std::find(iter->second[0].appIndexes_.begin(), iter->second[0].appIndexes_.end(),
117 resourceInfo.appIndex_) == iter->second[0].appIndexes_.end()) {
118 DeleteResourceInfo(name);
119 }
120 }
121 }
122 }
123
DeleteResourceInfo(const std::string & key)124 bool BundleResourceManager::DeleteResourceInfo(const std::string &key)
125 {
126 return bundleResourceRdb_->DeleteResourceInfo(key);
127 }
128
GetAllResourceName(std::vector<std::string> & keyNames)129 bool BundleResourceManager::GetAllResourceName(std::vector<std::string> &keyNames)
130 {
131 return bundleResourceRdb_->GetAllResourceName(keyNames);
132 }
133
GetBundleResourceInfo(const std::string & bundleName,const uint32_t flags,BundleResourceInfo & bundleResourceInfo,int32_t appIndex)134 bool BundleResourceManager::GetBundleResourceInfo(const std::string &bundleName, const uint32_t flags,
135 BundleResourceInfo &bundleResourceInfo, int32_t appIndex)
136 {
137 HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
138 APP_LOGD("start, bundleName:%{public}s", bundleName.c_str());
139 uint32_t resourceFlags = CheckResourceFlags(flags);
140 if (bundleResourceRdb_->GetBundleResourceInfo(bundleName, resourceFlags, bundleResourceInfo, appIndex)) {
141 APP_LOGD("success, bundleName:%{public}s", bundleName.c_str());
142 if (IsNeedProcessResourceIconInfo(resourceFlags)) {
143 int32_t userId = GetUserId();
144 std::vector<LauncherAbilityResourceInfo> resourceIconInfos;
145 if (!bundleResourceIconRdb_->GetResourceIconInfos(bundleName, userId, appIndex, resourceFlags,
146 resourceIconInfos) || resourceIconInfos.empty()) {
147 return true;
148 }
149 if (bundleName == CONTACTS_BUNDLE_NAME) {
150 BundleResourceThemeProcess::ProcessSpecialBundleResource(resourceIconInfos, bundleResourceInfo);
151 return true;
152 }
153 auto iter = std::find_if(resourceIconInfos.begin(), resourceIconInfos.end(),
154 [bundleName, appIndex](const auto resourceIconInfo) {
155 return ((resourceIconInfo.bundleName == bundleName) &&
156 (resourceIconInfo.appIndex == appIndex));
157 });
158 if (iter != resourceIconInfos.end()) {
159 bundleResourceInfo.icon = iter->icon;
160 bundleResourceInfo.foreground = iter->foreground;
161 bundleResourceInfo.background = iter->background;
162 }
163 }
164 return true;
165 }
166 auto bmsExtensionClient = std::make_shared<BmsExtensionClient>();
167 ErrCode ret = bmsExtensionClient->GetBundleResourceInfo(bundleName, resourceFlags, bundleResourceInfo, appIndex);
168 if (ret == ERR_OK) {
169 APP_LOGD("success, bundleName:%{public}s", bundleName.c_str());
170 return true;
171 }
172 APP_LOGE_NOFUNC("%{public}s not exist in resource rdb", bundleName.c_str());
173 return false;
174 }
175
GetLauncherAbilityResourceInfo(const std::string & bundleName,const uint32_t flags,std::vector<LauncherAbilityResourceInfo> & launcherAbilityResourceInfo,const int32_t appIndex)176 bool BundleResourceManager::GetLauncherAbilityResourceInfo(const std::string &bundleName, const uint32_t flags,
177 std::vector<LauncherAbilityResourceInfo> &launcherAbilityResourceInfo, const int32_t appIndex)
178 {
179 APP_LOGD("start, bundleName:%{public}s", bundleName.c_str());
180 uint32_t resourceFlags = CheckResourceFlags(flags);
181 if (bundleResourceRdb_->GetLauncherAbilityResourceInfo(bundleName, resourceFlags,
182 launcherAbilityResourceInfo, appIndex)) {
183 if (IsNeedProcessResourceIconInfo(resourceFlags)) {
184 int32_t userId = GetUserId();
185 std::vector<LauncherAbilityResourceInfo> resourceIconInfos;
186 if (!bundleResourceIconRdb_->GetResourceIconInfos(bundleName, userId, appIndex, resourceFlags,
187 resourceIconInfos) || resourceIconInfos.empty()) {
188 return true;
189 }
190 for (auto &resource : launcherAbilityResourceInfo) {
191 auto iter = std::find_if(resourceIconInfos.begin(), resourceIconInfos.end(),
192 [resource](const auto resourceIconInfo) {
193 return ((resource.bundleName == resourceIconInfo.bundleName) &&
194 (resource.moduleName == resourceIconInfo.moduleName) &&
195 (resource.abilityName == resourceIconInfo.abilityName) &&
196 (resource.appIndex == resourceIconInfo.appIndex));
197 });
198 if (iter == resourceIconInfos.end()) {
199 iter = std::find_if(resourceIconInfos.begin(), resourceIconInfos.end(),
200 [resource](const auto resourceIconInfo) {
201 return ((resource.bundleName == resourceIconInfo.bundleName) &&
202 (resource.appIndex == resourceIconInfo.appIndex));
203 });
204 }
205 if (iter != resourceIconInfos.end()) {
206 resource.icon = iter->icon;
207 resource.foreground = iter->foreground;
208 resource.background = iter->background;
209 }
210 }
211 }
212 return true;
213 }
214 auto bmsExtensionClient = std::make_shared<BmsExtensionClient>();
215 ErrCode ret = bmsExtensionClient->GetLauncherAbilityResourceInfo(bundleName, resourceFlags,
216 launcherAbilityResourceInfo, appIndex);
217 if (ret == ERR_OK) {
218 APP_LOGD("success, bundleName:%{public}s", bundleName.c_str());
219 return true;
220 }
221 APP_LOGE_NOFUNC("%{public}s not exist in resource rdb", bundleName.c_str());
222 return false;
223 }
224
GetAllBundleResourceInfo(const uint32_t flags,std::vector<BundleResourceInfo> & bundleResourceInfos)225 bool BundleResourceManager::GetAllBundleResourceInfo(const uint32_t flags,
226 std::vector<BundleResourceInfo> &bundleResourceInfos)
227 {
228 APP_LOGD("start");
229 uint32_t resourceFlags = CheckResourceFlags(flags);
230 if (bundleResourceRdb_->GetAllBundleResourceInfo(resourceFlags, bundleResourceInfos)) {
231 if (IsNeedProcessResourceIconInfo(resourceFlags)) {
232 int32_t userId = GetUserId();
233 std::vector<LauncherAbilityResourceInfo> resourceIconInfos;
234 if (!bundleResourceIconRdb_->GetAllResourceIconInfo(userId, resourceFlags, resourceIconInfos) ||
235 resourceIconInfos.empty()) {
236 return true;
237 }
238 for (auto &resource : bundleResourceInfos) {
239 if (resource.bundleName == CONTACTS_BUNDLE_NAME) {
240 BundleResourceThemeProcess::ProcessSpecialBundleResource(resourceIconInfos, resource);
241 continue;
242 }
243 auto iter = std::find_if(resourceIconInfos.begin(), resourceIconInfos.end(),
244 [resource](const auto resourceIconInfo) {
245 return ((resource.bundleName == resourceIconInfo.bundleName) &&
246 (resource.appIndex == resourceIconInfo.appIndex));
247 });
248 if (iter != resourceIconInfos.end()) {
249 resource.icon = iter->icon;
250 resource.foreground = iter->foreground;
251 resource.background = iter->background;
252 }
253 }
254 }
255 return true;
256 }
257 return false;
258 }
259
GetAllLauncherAbilityResourceInfo(const uint32_t flags,std::vector<LauncherAbilityResourceInfo> & launcherAbilityResourceInfos)260 bool BundleResourceManager::GetAllLauncherAbilityResourceInfo(const uint32_t flags,
261 std::vector<LauncherAbilityResourceInfo> &launcherAbilityResourceInfos)
262 {
263 APP_LOGD("start");
264 uint32_t resourceFlags = CheckResourceFlags(flags);
265 if (bundleResourceRdb_->GetAllLauncherAbilityResourceInfo(resourceFlags, launcherAbilityResourceInfos)) {
266 if (IsNeedProcessResourceIconInfo(resourceFlags)) {
267 int32_t userId = GetUserId();
268 std::vector<LauncherAbilityResourceInfo> resourceIconInfos;
269 if (!bundleResourceIconRdb_->GetAllResourceIconInfo(userId, resourceFlags, resourceIconInfos) ||
270 resourceIconInfos.empty()) {
271 return true;
272 }
273 for (auto &resource : launcherAbilityResourceInfos) {
274 auto iter = std::find_if(resourceIconInfos.begin(), resourceIconInfos.end(),
275 [resource](const auto resourceIconInfo) {
276 return ((resource.bundleName == resourceIconInfo.bundleName) &&
277 (resource.moduleName == resourceIconInfo.moduleName) &&
278 (resource.abilityName == resourceIconInfo.abilityName) &&
279 (resource.appIndex == resourceIconInfo.appIndex));
280 });
281 if (iter == resourceIconInfos.end()) {
282 iter = std::find_if(resourceIconInfos.begin(), resourceIconInfos.end(),
283 [resource](const auto resourceIconInfo) {
284 return ((resource.bundleName == resourceIconInfo.bundleName) &&
285 (resource.appIndex == resourceIconInfo.appIndex));
286 });
287 }
288 if (iter != resourceIconInfos.end()) {
289 resource.icon = iter->icon;
290 resource.foreground = iter->foreground;
291 resource.background = iter->background;
292 }
293 }
294 }
295 return true;
296 }
297 return false;
298 }
299
FilterLauncherAbilityResourceInfoWithFlag(const uint32_t flags,const std::string & bundleName,std::vector<LauncherAbilityResourceInfo> & launcherAbilityResourceInfos)300 bool BundleResourceManager::FilterLauncherAbilityResourceInfoWithFlag(const uint32_t flags,
301 const std::string &bundleName, std::vector<LauncherAbilityResourceInfo> &launcherAbilityResourceInfos)
302 {
303 if ((flags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ONLY_WITH_MAIN_ABILITY)) ==
304 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ONLY_WITH_MAIN_ABILITY)) {
305 std::vector<AbilityInfo> abilityInfos;
306 if (!GetLauncherAbilityInfos(bundleName, abilityInfos)) {
307 launcherAbilityResourceInfos.clear();
308 APP_LOGE("GetLauncherAbilityInfos failed");
309 return false;
310 }
311 launcherAbilityResourceInfos.erase(
312 std::remove_if(launcherAbilityResourceInfos.begin(), launcherAbilityResourceInfos.end(),
313 [this, &abilityInfos](const LauncherAbilityResourceInfo& resource) {
314 return !this->IsLauncherAbility(resource, abilityInfos);
315 }),
316 launcherAbilityResourceInfos.end()
317 );
318 }
319 return true;
320 }
321
GetLauncherAbilityInfos(const std::string & bundleName,std::vector<AbilityInfo> & abilityInfos)322 bool BundleResourceManager::GetLauncherAbilityInfos(const std::string &bundleName,
323 std::vector<AbilityInfo> &abilityInfos)
324 {
325 int32_t userId = Constants::UNSPECIFIED_USERID;
326 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
327 if (dataMgr == nullptr) {
328 APP_LOGE("dataMgr is nullptr");
329 return false;
330 }
331 Want want;
332 want.SetAction(Want::ACTION_HOME);
333 want.AddEntity(Want::ENTITY_HOME);
334 if (!bundleName.empty()) {
335 ElementName elementName;
336 elementName.SetBundleName(bundleName);
337 want.SetElement(elementName);
338 }
339 ErrCode ret = dataMgr->QueryLauncherAbilityInfos(want, userId, abilityInfos);
340 auto bmsExtensionClient = std::make_shared<BmsExtensionClient>();
341 ErrCode ans = bmsExtensionClient->QueryLauncherAbility(want, userId, abilityInfos);
342 if (ret != ERR_OK && ans != ERR_OK) {
343 APP_LOGE("GetLauncherAbilityInfos failed, ret:%{public}d, ans:%{public}d", ret, ans);
344 return false;
345 }
346 return true;
347 }
348
IsLauncherAbility(const LauncherAbilityResourceInfo & resourceInfo,std::vector<AbilityInfo> & abilityInfos)349 bool BundleResourceManager::IsLauncherAbility(const LauncherAbilityResourceInfo &resourceInfo,
350 std::vector<AbilityInfo> &abilityInfos)
351 {
352 for (const auto& abilityInfo : abilityInfos) {
353 if (resourceInfo.bundleName == abilityInfo.bundleName &&
354 resourceInfo.moduleName == abilityInfo.moduleName &&
355 resourceInfo.abilityName == abilityInfo.name) {
356 return true;
357 }
358 }
359 return false;
360 }
361
CheckResourceFlags(const uint32_t flags)362 uint32_t BundleResourceManager::CheckResourceFlags(const uint32_t flags)
363 {
364 APP_LOGD("flags:%{public}u", flags);
365 if (((flags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ALL)) ==
366 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ALL)) ||
367 ((flags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_LABEL)) ==
368 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_LABEL)) ||
369 ((flags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON)) ==
370 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON)) ||
371 ((flags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR)) ==
372 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR)) ||
373 ((flags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ONLY_WITH_MAIN_ABILITY)) ==
374 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ONLY_WITH_MAIN_ABILITY))) {
375 return flags;
376 }
377 APP_LOGD("illegal flags");
378 return flags | static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ALL);
379 }
380
ProcessResourceInfoWhenParseFailed(ResourceInfo & resourceInfo)381 void BundleResourceManager::ProcessResourceInfoWhenParseFailed(ResourceInfo &resourceInfo)
382 {
383 APP_LOGI("start, bundleName:%{public}s", resourceInfo.bundleName_.c_str());
384 if (resourceInfo.label_.empty()) {
385 resourceInfo.label_ = resourceInfo.bundleName_;
386 }
387 if (resourceInfo.bundleName_ == GLOBAL_RESOURCE_BUNDLE_NAME) {
388 APP_LOGE("%{public}s default resource parse failed", resourceInfo.bundleName_.c_str());
389 return;
390 }
391 if (resourceInfo.icon_.empty()) {
392 GetDefaultIcon(resourceInfo);
393 }
394 }
395
GetDefaultIcon(ResourceInfo & resourceInfo)396 void BundleResourceManager::GetDefaultIcon(ResourceInfo &resourceInfo)
397 {
398 BundleResourceInfo bundleResourceInfo;
399 if (!GetBundleResourceInfo(GLOBAL_RESOURCE_BUNDLE_NAME,
400 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON) |
401 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR),
402 bundleResourceInfo)) {
403 APP_LOGE("get default icon failed");
404 return;
405 }
406 resourceInfo.icon_ = bundleResourceInfo.icon;
407 resourceInfo.foreground_ = bundleResourceInfo.foreground;
408 resourceInfo.background_ = bundleResourceInfo.background;
409 }
410
SendBundleResourcesChangedEvent(const int32_t userId,const uint32_t type)411 void BundleResourceManager::SendBundleResourcesChangedEvent(const int32_t userId, const uint32_t type)
412 {
413 APP_LOGI("send bundleResource event, userId:%{public}d type:%{public}u", userId, type);
414 std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>();
415 commonEventMgr->NotifyBundleResourcesChanged(userId, type);
416 }
417
GetTargetBundleName(const std::string & bundleName,std::string & targetBundleName)418 void BundleResourceManager::GetTargetBundleName(const std::string &bundleName, std::string &targetBundleName)
419 {
420 APP_LOGD("start");
421 BundleResourceProcess::GetTargetBundleName(bundleName, targetBundleName);
422 }
423
GetBundleResourceInfoForCloneBundle(const std::string & bundleName,const int32_t appIndex,const uint32_t type,std::vector<ResourceInfo> & resourceInfos)424 bool BundleResourceManager::GetBundleResourceInfoForCloneBundle(const std::string &bundleName,
425 const int32_t appIndex, const uint32_t type, std::vector<ResourceInfo> &resourceInfos)
426 {
427 uint32_t flags = 0;
428 if ((type & static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE)) ==
429 static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE)) {
430 flags |= static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR) |
431 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON);
432 }
433 if ((type & static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE)) ==
434 static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE)) {
435 flags |= static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_LABEL);
436 }
437 // 1. get main bundle resource info
438 BundleResourceInfo bundleResourceInfo;
439 if (!bundleResourceRdb_->GetBundleResourceInfo(bundleName, flags, bundleResourceInfo)) {
440 APP_LOGE("get resource failed %{public}s appIndex:%{public}d", bundleName.c_str(), appIndex);
441 return false;
442 }
443 bundleResourceInfo.appIndex = appIndex;
444 ResourceInfo bundleResource;
445 bundleResource.ConvertFromBundleResourceInfo(bundleResourceInfo);
446 resourceInfos.emplace_back(bundleResource);
447 // 2. get main launcher ability resource info
448 std::vector<LauncherAbilityResourceInfo> launcherAbilityResourceInfos;
449 if (!bundleResourceRdb_->GetLauncherAbilityResourceInfo(bundleName, flags, launcherAbilityResourceInfos)) {
450 APP_LOGW("get ability resource failed %{public}s appIndex:%{public}d",
451 bundleName.c_str(), appIndex);
452 }
453 for (auto &launcherAbility : launcherAbilityResourceInfos) {
454 launcherAbility.appIndex = appIndex;
455 ResourceInfo launcherResource;
456 launcherResource.ConvertFromLauncherAbilityResourceInfo(launcherAbility);
457 resourceInfos.emplace_back(launcherResource);
458 }
459 // 3. get extension ability resource info
460 std::vector<LauncherAbilityResourceInfo> extensionAbilityResourceInfos;
461 bundleResourceRdb_->GetAllExtensionAbilityResourceInfo(bundleName, flags, extensionAbilityResourceInfos);
462 for (auto &extensionAbility : extensionAbilityResourceInfos) {
463 extensionAbility.appIndex = appIndex;
464 ResourceInfo extensionResource;
465 extensionResource.ConvertFromLauncherAbilityResourceInfo(extensionAbility);
466 resourceInfos.emplace_back(extensionResource);
467 }
468 APP_LOGI("%{public}s appIndex:%{public}d add resource size:%{public}zu", bundleName.c_str(), appIndex,
469 resourceInfos.size());
470 return true;
471 }
472
DeleteNotExistResourceInfo()473 bool BundleResourceManager::DeleteNotExistResourceInfo()
474 {
475 APP_LOGD("start delete not exist resource");
476 return bundleResourceRdb_->DeleteNotExistResourceInfo();
477 }
478
GetExtensionAbilityResourceInfo(const std::string & bundleName,const ExtensionAbilityType extensionAbilityType,const uint32_t flags,std::vector<LauncherAbilityResourceInfo> & extensionAbilityResourceInfo,const int32_t appIndex)479 bool BundleResourceManager::GetExtensionAbilityResourceInfo(const std::string &bundleName,
480 const ExtensionAbilityType extensionAbilityType, const uint32_t flags,
481 std::vector<LauncherAbilityResourceInfo> &extensionAbilityResourceInfo, const int32_t appIndex)
482 {
483 APP_LOGD("start, bundleName:%{public}s", bundleName.c_str());
484 uint32_t resourceFlags = CheckResourceFlags(flags);
485 if (bundleResourceRdb_->GetExtensionAbilityResourceInfo(bundleName, extensionAbilityType, resourceFlags,
486 extensionAbilityResourceInfo, appIndex)) {
487 return true;
488 }
489 APP_LOGE_NOFUNC("%{public}s extension ability %{public}d not exist in resource rdb", bundleName.c_str(),
490 extensionAbilityType);
491 return false;
492 }
493
ProcessResourceInfoNoNeedToParseOtherIcon(std::vector<ResourceInfo> & resourceInfos)494 void BundleResourceManager::ProcessResourceInfoNoNeedToParseOtherIcon(std::vector<ResourceInfo> &resourceInfos)
495 {
496 size_t size = resourceInfos.size();
497 for (size_t index = 0; index < size; ++index) {
498 // theme changed no need parse label
499 resourceInfos[index].labelNeedParse_ = false;
500 resourceInfos[index].label_ = Constants::EMPTY_STRING;
501 if ((index > 0) && ServiceConstants::ALLOW_MULTI_ICON_BUNDLE.find(resourceInfos[0].bundleName_) ==
502 ServiceConstants::ALLOW_MULTI_ICON_BUNDLE.end()) {
503 // only need parse once
504 resourceInfos[index].iconNeedParse_ = false;
505 }
506 }
507 }
508
PrepareSysRes()509 void BundleResourceManager::PrepareSysRes()
510 {
511 {
512 std::lock_guard<std::mutex> guard(g_sysResMutex);
513 if (!g_resMgr) {
514 g_resMgr = std::shared_ptr<Global::Resource::ResourceManager>(
515 Global::Resource::CreateResourceManager());
516 APP_LOGI("get system resource");
517 }
518 }
519 auto task = [] {
520 std::lock_guard<std::mutex> guard(g_sysResMutex);
521 g_resMgr = nullptr;
522 APP_LOGI("release system resource");
523 };
524 delayedTaskMgr_->ScheduleDelayedTask(task);
525 }
526
AddResourceInfoByBundleNameWhenInstall(const std::string & bundleName,const int32_t userId,const bool isBundleFirstInstall)527 bool BundleResourceManager::AddResourceInfoByBundleNameWhenInstall(
528 const std::string &bundleName, const int32_t userId, const bool isBundleFirstInstall)
529 {
530 // 1. get all resourceInfos by bundleName
531 std::vector<ResourceInfo> resourceInfos;
532 if (!BundleResourceProcess::GetResourceInfoByBundleName(bundleName, userId, resourceInfos, 0, false)) {
533 APP_LOGE("get resource by -n %{public}s -u %{public}d failed", bundleName.c_str(), userId);
534 return false;
535 }
536 // not first install need delete resource
537 if (!isBundleFirstInstall) {
538 DeleteNotExistResourceInfo(bundleName, 0, resourceInfos);
539 }
540 PrepareSysRes();
541 // 2. parse icon and label resource with hap files
542 BundleResourceParser parser;
543 if (!parser.ParseResourceInfosNoTheme(userId, resourceInfos)) {
544 APP_LOGW_NOFUNC("-n %{public}s Parse failed, need to modify label and icon", bundleName.c_str());
545 ProcessResourceInfoWhenParseFailed(resourceInfos[0]);
546 }
547 // 3. add original resource information to bundleResourceRdb
548 bool ret = bundleResourceRdb_->AddResourceInfos(resourceInfos);
549 if (!ret) {
550 APP_LOGE("add resource failed when install -n %{public}s -u %{public}d", bundleName.c_str(), userId);
551 }
552 // 4. if isBundleFirstInstall false, need to process clone bundle resource
553 if (!isBundleFirstInstall && !resourceInfos.empty() && !resourceInfos[0].appIndexes_.empty()) {
554 for (const int32_t appIndex : resourceInfos[0].appIndexes_) {
555 DeleteNotExistResourceInfo(bundleName, appIndex, resourceInfos);
556 // update clone bundle, label and icon
557 (void)ProcessCloneBundleResourceInfo(resourceInfos[0].bundleName_, appIndex);
558 }
559 }
560 // 5. if theme not exist, then return
561 if (!BundleResourceThemeProcess::IsBundleThemeExist(bundleName, userId)) {
562 return ret;
563 }
564 std::vector<ResourceInfo> themeResourceInfos;
565 themeResourceInfos.emplace_back(resourceInfos[0]);
566 // 5. traverse all resourceInfo to determine if ability theme exist
567 for (const auto &resource : resourceInfos) {
568 if (BundleResourceThemeProcess::IsAbilityThemeExist(resource.bundleName_, resource.moduleName_,
569 resource.abilityName_, userId)) {
570 themeResourceInfos.emplace_back(resource);
571 }
572 }
573 // clear icon data
574 for (auto resource : themeResourceInfos) {
575 resource.icon_ = "";
576 resource.foreground_.clear();
577 resource.background_.clear();
578 }
579 // 6. parse resource with theme
580 if (!parser.ParseIconResourceInfosWithTheme(userId, themeResourceInfos)) {
581 APP_LOGE("parse theme resource failed -n %{public}s -u %{public}d", bundleName.c_str(), userId);
582 return false;
583 }
584 // 7. add theme resource to bundleResourceIconRdb
585 if (!bundleResourceIconRdb_->AddResourceIconInfos(userId, IconResourceType::THEME_ICON, themeResourceInfos)) {
586 APP_LOGE("add theme resource failed -n %{public}s -u %{public}d", bundleName.c_str(), userId);
587 return false;
588 }
589 return ret;
590 }
591
AddResourceInfoByBundleNameWhenUpdate(const std::string & bundleName,const int32_t userId)592 bool BundleResourceManager::AddResourceInfoByBundleNameWhenUpdate(
593 const std::string &bundleName, const int32_t userId)
594 {
595 // 1. get all resource
596 std::vector<ResourceInfo> resourceInfos;
597 if (!BundleResourceProcess::GetResourceInfoByBundleName(bundleName, userId, resourceInfos, 0, false) ||
598 resourceInfos.empty()) {
599 APP_LOGE("get resource bundleName %{public}s userId %{public}d failed",
600 bundleName.c_str(), userId);
601 return false;
602 }
603 // 2. delete ability resource when update, module or ability may changed
604 DeleteNotExistResourceInfo(bundleName, 0, resourceInfos);
605 PrepareSysRes();
606 // 3. parse icon and label resource with hap files
607 BundleResourceParser parser;
608 if (!parser.ParseResourceInfosNoTheme(userId, resourceInfos)) {
609 APP_LOGW_NOFUNC("key:%{public}s Parse failed, need to modify label and icon",
610 resourceInfos[0].GetKey().c_str());
611 ProcessResourceInfoWhenParseFailed(resourceInfos[0]);
612 }
613 // 4. add original resource information to bundleResourceRdb
614 bool ret = bundleResourceRdb_->AddResourceInfos(resourceInfos);
615 if (!ret) {
616 APP_LOGE("add resource failed when update -n %{public}s -u %{public}d", bundleName.c_str(), userId);
617 }
618 /**
619 * 5. no need to consider theme and dynamic icon when bundle update,
620 * need to update clone bundle resource (original resource information) in bundleResourceRdb
621 */
622 if (!resourceInfos.empty() && !resourceInfos[0].appIndexes_.empty()) {
623 for (const int32_t appIndex : resourceInfos[0].appIndexes_) {
624 DeleteNotExistResourceInfo(bundleName, appIndex, resourceInfos);
625 // 6. update clone bundle, label and icon
626 if (!ProcessCloneBundleResourceInfo(resourceInfos[0].bundleName_, appIndex)) {
627 APP_LOGW("-n %{public}s -i %{public}d add clone resource failed", bundleName.c_str(), appIndex);
628 }
629 }
630 }
631 return ret;
632 }
633
ProcessCloneBundleResourceInfo(const std::string & bundleName,const int32_t appIndex)634 bool BundleResourceManager::ProcessCloneBundleResourceInfo(
635 const std::string &bundleName, const int32_t appIndex)
636 {
637 APP_LOGD("start update clone bundle resource info, bundleName:%{public}s appIndex:%{public}d",
638 bundleName.c_str(), appIndex);
639 uint32_t type = static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE) |
640 static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE);
641 // 1. get main bundle resource info
642 std::vector<ResourceInfo> resourceInfos;
643 if (!GetBundleResourceInfoForCloneBundle(bundleName, appIndex, type, resourceInfos)) {
644 APP_LOGE("add clone bundle resource failed, bundleName:%{public}s appIndex:%{public}d",
645 bundleName.c_str(), appIndex);
646 return false;
647 }
648 // 2. need to process base icon and badge icon
649 BundleResourceParser parser;
650 if (!parser.ParserCloneResourceInfo(appIndex, resourceInfos)) {
651 APP_LOGE("bundleName:%{public}s appIndex:%{public}d parse clone resource failed",
652 bundleName.c_str(), appIndex);
653 }
654 // 3. add clone bundle resource info
655 if (!bundleResourceRdb_->AddResourceInfos(resourceInfos)) {
656 APP_LOGE("add resource failed, bundleName:%{public}s appIndex:%{public}d", bundleName.c_str(), appIndex);
657 return false;
658 }
659 APP_LOGD("end, add clone bundle resource succeed");
660 return true;
661 }
662
AddResourceInfoByBundleNameWhenCreateUser(const std::string & bundleName,const int32_t userId)663 bool BundleResourceManager::AddResourceInfoByBundleNameWhenCreateUser(
664 const std::string &bundleName, const int32_t userId)
665 {
666 // 1. if theme not exist, then return
667 if (!BundleResourceThemeProcess::IsBundleThemeExist(bundleName, userId)) {
668 return true;
669 }
670 // 2. get all resource
671 std::vector<ResourceInfo> resourceInfos;
672 if (!BundleResourceProcess::GetResourceInfoByBundleName(bundleName, userId, resourceInfos, 0, false) ||
673 resourceInfos.empty()) {
674 APP_LOGE("get all resource failed when create user -n %{public}s -u %{public}d",
675 bundleName.c_str(), userId);
676 return false;
677 }
678 PrepareSysRes();
679 std::vector<ResourceInfo> themeResourceInfos;
680 themeResourceInfos.emplace_back(resourceInfos[0]);
681 // 3. traverse all resourceInfo to determine if ability theme exist
682 for (const auto &resource : resourceInfos) {
683 if (BundleResourceThemeProcess::IsAbilityThemeExist(resource.bundleName_, resource.moduleName_,
684 resource.abilityName_, userId)) {
685 themeResourceInfos.emplace_back(resource);
686 }
687 }
688 // 4. parse theme icon, no need to add hapPath
689 BundleResourceParser parser;
690 if (!parser.ParseIconResourceInfosWithTheme(userId, themeResourceInfos)) {
691 APP_LOGE("parse theme icon failed when create user -n %{public}s -u %{public}d", bundleName.c_str(), userId);
692 return false;
693 }
694 // 5. add theme icon to bundleResourceIconRdb
695 if (!bundleResourceIconRdb_->AddResourceIconInfos(userId, IconResourceType::THEME_ICON, themeResourceInfos)) {
696 APP_LOGE("add theme icon failed when create user -n %{public}s -u %{public}d", bundleName.c_str(), userId);
697 return false;
698 }
699 // 6. process bundle clone resource
700 if (!resourceInfos.empty() && !resourceInfos[0].appIndexes_.empty()) {
701 for (const int32_t appIndex : resourceInfos[0].appIndexes_) {
702 // update clone bundle icon resource
703 (void)ProcessCloneBundleResourceInfoWhenSystemThemeChanged(bundleName, userId, appIndex);
704 }
705 }
706 return true;
707 }
708
DeleteBundleResourceInfo(const std::string & bundleName,const int32_t userId,const bool isExistInOtherUser)709 bool BundleResourceManager::DeleteBundleResourceInfo(
710 const std::string &bundleName,
711 const int32_t userId,
712 const bool isExistInOtherUser)
713 {
714 /**
715 * Delete bundle resource when uninstall, but bundle still exists in other users.
716 * if isExistInOtherUser false, need to delete resource in bundleResourceIconRdb and bundleResourceRdb.
717 * if isExistInOtherUser true, Only need to delete resource in bundleResourceIconRdb.
718 */
719 bool ret = true;
720 if (!isExistInOtherUser) {
721 ret = bundleResourceRdb_->DeleteResourceInfo(bundleName);
722 if (!ret) {
723 APP_LOGE("delete -n %{public}s -u %{public}d in bundleResourceRdb failed", bundleName.c_str(), userId);
724 }
725 }
726
727 if (!bundleResourceIconRdb_->DeleteResourceIconInfos(bundleName, userId)) {
728 APP_LOGE("delete -n %{public}s -u %{public}d in bundleResourceIconRdb failed", bundleName.c_str(), userId);
729 return false;
730 }
731 return ret;
732 }
733
AddDynamicIconResource(const std::string & bundleName,const int32_t userId,const int32_t appIndex,ResourceInfo & resourceInfo)734 bool BundleResourceManager::AddDynamicIconResource(
735 const std::string &bundleName, const int32_t userId, const int32_t appIndex, ResourceInfo &resourceInfo)
736 {
737 // only need to process bundleResourceIconRdb
738 resourceInfo.bundleName_ = bundleName;
739 resourceInfo.appIndex_ = appIndex;
740 if (userId != Constants::UNSPECIFIED_USERID) {
741 if (!bundleResourceIconRdb_->AddResourceIconInfo(userId, IconResourceType::DYNAMIC_ICON, resourceInfo)) {
742 APP_LOGE("add dynamic icon failed -n %{public}s -u %{public}d -a %{public}d",
743 bundleName.c_str(), userId, appIndex);
744 return false;
745 }
746 return true;
747 }
748 // if userId == -2, process all user and clone bundle
749 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
750 if (dataMgr == nullptr) {
751 APP_LOGE("dataMgr is nullptr");
752 return false;
753 }
754 bool ret = true;
755 auto userIds = dataMgr->GetUserIds(bundleName);
756 for (const auto &user : userIds) {
757 resourceInfo.appIndex_ = 0;
758 ret &= bundleResourceIconRdb_->AddResourceIconInfo(user, IconResourceType::DYNAMIC_ICON, resourceInfo);
759 auto appIndexes = dataMgr->GetCloneAppIndexes(bundleName, user);
760 for (const auto &index : appIndexes) {
761 resourceInfo.appIndex_ = index;
762 ret &= bundleResourceIconRdb_->AddResourceIconInfo(user, IconResourceType::DYNAMIC_ICON, resourceInfo);
763 }
764 }
765 if (!ret) {
766 APP_LOGE("add all user dynamic icon failed -n %{public}s -u %{public}d -a %{public}d",
767 bundleName.c_str(), userId, appIndex);
768 }
769 return ret;
770 }
771
DeleteDynamicIconResource(const std::string & bundleName,const int32_t userId,const int32_t appIndex)772 bool BundleResourceManager::DeleteDynamicIconResource(
773 const std::string &bundleName, const int32_t userId, const int32_t appIndex)
774 {
775 if (userId != Constants::UNSPECIFIED_USERID) {
776 if (!bundleResourceIconRdb_->DeleteResourceIconInfo(bundleName, userId, appIndex,
777 IconResourceType::DYNAMIC_ICON)) {
778 APP_LOGE("delete dynamic icon failed -n %{public}s -u %{public}d -a %{public}d",
779 bundleName.c_str(), userId, appIndex);
780 return false;
781 }
782 return true;
783 }
784 // if userId is -2, need delete all userId and appIndex dynamic icon
785 if (!bundleResourceIconRdb_->DeleteResourceIconInfos(bundleName, IconResourceType::DYNAMIC_ICON)) {
786 APP_LOGE("delete all user dynamic icon failed -n %{public}s -u %{public}d -a %{public}d",
787 bundleName.c_str(), userId, appIndex);
788 return false;
789 }
790 return true;
791 }
792
AddAllResourceInfo(const int32_t userId,const uint32_t type)793 bool BundleResourceManager::AddAllResourceInfo(
794 const int32_t userId, const uint32_t type)
795 {
796 HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
797 EventReport::SendCpuSceneEvent(FOUNDATION_PROCESS_NAME, SCENE_ID_UPDATE_RESOURCE);
798 ++currentTaskNum_;
799 uint32_t tempTaskNum = currentTaskNum_;
800 std::lock_guard<std::mutex> guard(mutex_);
801 APP_LOGI("bundle resource hold mutex");
802 std::map<std::string, std::vector<ResourceInfo>> resourceInfosMap;
803 if (!BundleResourceProcess::GetAllResourceInfo(userId, resourceInfosMap)) {
804 APP_LOGE("GetAllResourceInfo failed userId %{public}d", userId);
805 return false;
806 }
807 PrepareSysRes();
808 if ((type & static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE)) ==
809 static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_THEME_CHANGE)) {
810 if (!AddResourceInfosWhenSystemThemeChanged(resourceInfosMap, userId, tempTaskNum)) {
811 APP_LOGE("add resource failed when theme changed -u %{public}d", userId);
812 return false;
813 }
814 }
815 if ((type & static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE)) ==
816 static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE)) {
817 if (!AddResourceInfosWhenSystemLanguageChanged(resourceInfosMap, userId, tempTaskNum)) {
818 APP_LOGE("add resource failed when language changed -u %{public}d", userId);
819 return false;
820 }
821 }
822 SendBundleResourcesChangedEvent(userId, type);
823 APP_LOGI_NOFUNC("add all resource end");
824 return true;
825 }
826
AddResourceInfosWhenSystemLanguageChanged(std::map<std::string,std::vector<ResourceInfo>> & resourceInfosMap,const int32_t userId,const uint32_t tempTaskNumber)827 bool BundleResourceManager::AddResourceInfosWhenSystemLanguageChanged(
828 std::map<std::string, std::vector<ResourceInfo>> &resourceInfosMap,
829 const int32_t userId, const uint32_t tempTaskNumber)
830 {
831 HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
832 if (resourceInfosMap.empty()) {
833 APP_LOGE("resourceInfosMap is empty");
834 return false;
835 }
836 InnerProcessResourceInfoBySystemLanguageChanged(resourceInfosMap);
837 std::shared_ptr<ThreadPool> threadPool = std::make_shared<ThreadPool>(THREAD_POOL_NAME);
838 threadPool->Start(MAX_TASK_NUMBER);
839 threadPool->SetMaxTaskNum(MAX_TASK_NUMBER);
840 for (const auto &item : resourceInfosMap) {
841 if (tempTaskNumber != currentTaskNum_) {
842 APP_LOGI("need stop current task, new first");
843 threadPool->Stop();
844 return false;
845 }
846 std::string bundleName = item.first;
847 auto task = [userId, bundleName, &resourceInfosMap, this]() {
848 if (resourceInfosMap.find(bundleName) == resourceInfosMap.end()) {
849 APP_LOGE("bundleName %{public}s not exist", bundleName.c_str());
850 return;
851 }
852 std::vector<ResourceInfo> resourceInfos = resourceInfosMap[bundleName];
853 BundleResourceParser parser;
854 parser.ParseResourceInfos(userId, resourceInfos);
855 bundleResourceRdb_->UpdateResourceForSystemStateChanged(resourceInfos);
856 };
857 threadPool->AddTask(task);
858 }
859 while (threadPool->GetCurTaskNum() > 0) {
860 std::this_thread::sleep_for(std::chrono::milliseconds(CHECK_INTERVAL));
861 }
862 threadPool->Stop();
863 // process clone bundle resource info, only flash label
864 for (const auto &item : resourceInfosMap) {
865 if (!item.second.empty() && !item.second[0].appIndexes_.empty()) {
866 APP_LOGI("start process bundle:%{public}s clone resource info", item.first.c_str());
867 for (const int32_t appIndex : item.second[0].appIndexes_) {
868 ProcessCloneBundleResourceInfoWhenSystemLanguageChanged(item.first, userId, appIndex);
869 }
870 }
871 }
872 APP_LOGI("all task end resource size %{public}zu when language changed", resourceInfosMap.size());
873 return true;
874 }
875
ProcessCloneBundleResourceInfoWhenSystemLanguageChanged(const std::string & bundleName,const int32_t userId,const int32_t appIndex)876 bool BundleResourceManager::ProcessCloneBundleResourceInfoWhenSystemLanguageChanged(
877 const std::string &bundleName,
878 const int32_t userId,
879 const int32_t appIndex)
880 {
881 if (appIndex <= 0) {
882 APP_LOGE("prase clone bundle failed -n %{public}s -u %{public}d -a %{public}d", bundleName.c_str(),
883 userId, appIndex);
884 return false;
885 }
886 std::vector<ResourceInfo> resourceInfos;
887 if (!GetBundleResourceInfoForCloneBundle(bundleName, appIndex,
888 static_cast<uint32_t>(BundleResourceChangeType::SYSTEM_LANGUE_CHANGE), resourceInfos)) {
889 APP_LOGE("get clone bundle resource failed -n %{public}s -u %{public}d -a %{public}d",
890 bundleName.c_str(), userId, appIndex);
891 return false;
892 }
893 // update clone bundle label resource
894 if (!bundleResourceRdb_->UpdateResourceForSystemStateChanged(resourceInfos)) {
895 APP_LOGE("update clone resource failed -n %{public}s -u %{public}d -a %{public}d", bundleName.c_str(),
896 userId, appIndex);
897 return false;
898 }
899 return true;
900 }
901
DeleteNotExistThemeResource(const std::map<std::string,std::vector<ResourceInfo>> & resourceInfosMap,const std::set<std::string> & oldResourceNames,const int32_t userId)902 void BundleResourceManager::DeleteNotExistThemeResource(
903 const std::map<std::string, std::vector<ResourceInfo>> &resourceInfosMap,
904 const std::set<std::string> &oldResourceNames,
905 const int32_t userId)
906 {
907 if (oldResourceNames.empty()) {
908 return;
909 }
910 std::set<std::string> newBundleNames;
911 for (const auto &item : resourceInfosMap) {
912 for (const auto &resource : item.second) {
913 newBundleNames.insert(resource.GetKey());
914 }
915 }
916 for (const auto &name : oldResourceNames) {
917 if (newBundleNames.find(name) == newBundleNames.end()) {
918 // delete key bundleName and type, need delete clone bundle
919 (void)bundleResourceIconRdb_->DeleteResourceIconInfos(name, userId, IconResourceType::THEME_ICON);
920 }
921 }
922 }
923
AddResourceInfosWhenSystemThemeChanged(std::map<std::string,std::vector<ResourceInfo>> & resourceInfosMap,const int32_t userId,const uint32_t tempTaskNumber)924 bool BundleResourceManager::AddResourceInfosWhenSystemThemeChanged(
925 std::map<std::string, std::vector<ResourceInfo>> &resourceInfosMap,
926 const int32_t userId, const uint32_t tempTaskNumber)
927 {
928 HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
929 if (resourceInfosMap.empty()) {
930 APP_LOGE("resourceInfosMap is empty");
931 return false;
932 }
933 // 1. used to delete no exist in current theme bundle resource
934 std::set<std::string> oldResourceNames;
935 if (!bundleResourceIconRdb_->GetAllResourceIconName(userId, oldResourceNames, IconResourceType::THEME_ICON)) {
936 APP_LOGW("get old bundle names failed");
937 }
938 // 2. judge whether the bundle theme exists
939 InnerProcessResourceInfoBySystemThemeChanged(resourceInfosMap, userId);
940 std::shared_ptr<ThreadPool> threadPool = std::make_shared<ThreadPool>(THREAD_POOL_NAME);
941 threadPool->Start(MAX_TASK_NUMBER);
942 threadPool->SetMaxTaskNum(MAX_TASK_NUMBER);
943 for (const auto &item : resourceInfosMap) {
944 if (tempTaskNumber != currentTaskNum_) {
945 APP_LOGI("need stop current task, new first");
946 threadPool->Stop();
947 return false;
948 }
949 std::string bundleName = item.first;
950 auto task = [userId, bundleName, &resourceInfosMap, this]() {
951 if (resourceInfosMap.find(bundleName) == resourceInfosMap.end()) {
952 APP_LOGE("bundleName %{public}s not exist", bundleName.c_str());
953 return;
954 }
955 std::vector<ResourceInfo> resourceInfos = resourceInfosMap[bundleName];
956 BundleResourceParser parser;
957 parser.ParseIconResourceInfosWithTheme(userId, resourceInfos);
958 (void)bundleResourceIconRdb_->AddResourceIconInfos(userId, IconResourceType::THEME_ICON, resourceInfos);
959 };
960 threadPool->AddTask(task);
961 }
962 while (threadPool->GetCurTaskNum() > 0) {
963 std::this_thread::sleep_for(std::chrono::milliseconds(CHECK_INTERVAL));
964 }
965 threadPool->Stop();
966 // process clone bundle resource info
967 for (const auto &item : resourceInfosMap) {
968 if (!item.second.empty() && !item.second[0].appIndexes_.empty()) {
969 APP_LOGI("start process bundle:%{public}s clone resource info", item.first.c_str());
970 for (const int32_t appIndex : item.second[0].appIndexes_) {
971 (void)ProcessCloneBundleResourceInfoWhenSystemThemeChanged(item.first, userId, appIndex);
972 }
973 }
974 }
975 DeleteNotExistThemeResource(resourceInfosMap, oldResourceNames, userId);
976 // set is online theme
977 SetIsOnlineTheme(userId);
978 APP_LOGI("all task end resource size %{public}zu when theme changed", resourceInfosMap.size());
979 return true;
980 }
981
ProcessCloneBundleResourceInfoWhenSystemThemeChanged(const std::string & bundleName,const int32_t userId,const int32_t appIndex)982 bool BundleResourceManager::ProcessCloneBundleResourceInfoWhenSystemThemeChanged(
983 const std::string &bundleName,
984 const int32_t userId,
985 const int32_t appIndex)
986 {
987 // 1. query main bundle resource in bundleResourceIconRdb
988 std::vector<LauncherAbilityResourceInfo> launcherAbilityResourceInfos;
989 if (!bundleResourceIconRdb_->GetResourceIconInfos(bundleName, userId, 0,
990 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON) |
991 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR),
992 launcherAbilityResourceInfos, IconResourceType::THEME_ICON)) {
993 APP_LOGE("get resource failed -n %{public}s -u %{public}d -a %{public}d",
994 bundleName.c_str(), userId, appIndex);
995 return false;
996 }
997 std::vector<ResourceInfo> resourceInfos;
998 for (auto &info : launcherAbilityResourceInfos) {
999 info.appIndex = appIndex;
1000 ResourceInfo bundleResource;
1001 bundleResource.ConvertFromLauncherAbilityResourceInfo(info);
1002 resourceInfos.emplace_back(bundleResource);
1003 }
1004 // 2. process icon with badge
1005 BundleResourceParser parser;
1006 if (!parser.ParserCloneResourceInfo(appIndex, resourceInfos)) {
1007 APP_LOGE("parse clone resource failed -n %{public}s -u %{public}d -a %{public}d",
1008 bundleName.c_str(), userId, appIndex);
1009 }
1010 // 3. save clone bundle resource info to bundleResourceIconRdb
1011 if (!bundleResourceIconRdb_->AddResourceIconInfos(userId, IconResourceType::THEME_ICON, resourceInfos)) {
1012 APP_LOGE("add resource failed -n %{public}s -u %{public}d -a %{public}d",
1013 bundleName.c_str(), userId, appIndex);
1014 return false;
1015 }
1016 return true;
1017 }
1018
InnerProcessResourceInfoBySystemThemeChanged(std::map<std::string,std::vector<ResourceInfo>> & resourceInfosMap,const int32_t userId)1019 void BundleResourceManager::InnerProcessResourceInfoBySystemThemeChanged(
1020 std::map<std::string, std::vector<ResourceInfo>> &resourceInfosMap,
1021 const int32_t userId)
1022 {
1023 for (auto iter = resourceInfosMap.begin(); iter != resourceInfosMap.end();) {
1024 if (iter->second.empty() || !BundleResourceThemeProcess::IsBundleThemeExist(iter->first, userId)) {
1025 iter = resourceInfosMap.erase(iter);
1026 continue;
1027 }
1028 std::vector<ResourceInfo> themeResourceInfos;
1029 themeResourceInfos.emplace_back(iter->second[0]);
1030 for (const auto &resource : iter->second) {
1031 if (BundleResourceThemeProcess::IsAbilityThemeExist(resource.bundleName_, resource.moduleName_,
1032 resource.abilityName_, userId)) {
1033 themeResourceInfos.emplace_back(resource);
1034 }
1035 }
1036 iter->second = themeResourceInfos;
1037 ++iter;
1038 }
1039 for (auto iter = resourceInfosMap.begin(); iter != resourceInfosMap.end(); ++iter) {
1040 ProcessResourceInfoNoNeedToParseOtherIcon(iter->second);
1041 }
1042 }
1043
AddCloneBundleResourceInfoWhenInstall(const std::string & bundleName,const int32_t userId,const int32_t appIndex,const bool isExistInOtherUser)1044 bool BundleResourceManager::AddCloneBundleResourceInfoWhenInstall(
1045 const std::string &bundleName,
1046 const int32_t userId,
1047 const int32_t appIndex,
1048 const bool isExistInOtherUser)
1049 {
1050 /**
1051 * Need to distinguish whether bundle and appIndex exist in other users.
1052 * if not exist, need to process both bundleResourceRdb and bundleResourceIconRdb;
1053 * if exist, only need to process bundleResourceIconRdb.
1054 */
1055 PrepareSysRes();
1056 bool ret = true;
1057 if (!isExistInOtherUser) {
1058 // 1. process clone resource icon and label in bundleResourceRdb, icon with badge, label with appIndex
1059 ret = ProcessCloneBundleResourceInfo(bundleName, appIndex);
1060 if (!ret) {
1061 APP_LOGE("-n %{public}s -u %{public}d -a %{public}d process clone resource failed",
1062 bundleName.c_str(), userId, appIndex);
1063 }
1064 }
1065 // 2. if theme not exist, then return
1066 if (!BundleResourceThemeProcess::IsBundleThemeExist(bundleName, userId)) {
1067 return ret;
1068 }
1069 // 3. process clone resource icon in bundleResourceIconRdb
1070 std::vector<LauncherAbilityResourceInfo> launcherAbilityResourceInfos;
1071 if (!bundleResourceIconRdb_->GetResourceIconInfos(bundleName, userId, 0,
1072 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON) |
1073 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR),
1074 launcherAbilityResourceInfos, IconResourceType::THEME_ICON)) {
1075 APP_LOGE("get resource failed -n %{public}s -u %{public}d -a %{public}d",
1076 bundleName.c_str(), userId, appIndex);
1077 return false;
1078 }
1079 // 4. process icon with badge
1080 std::vector<ResourceInfo> resourceInfos;
1081 for (auto &info : launcherAbilityResourceInfos) {
1082 info.appIndex = appIndex;
1083 ResourceInfo bundleResource;
1084 bundleResource.ConvertFromLauncherAbilityResourceInfo(info);
1085 resourceInfos.emplace_back(bundleResource);
1086 }
1087 BundleResourceParser parser;
1088 if (!parser.ParserCloneResourceInfo(appIndex, resourceInfos)) {
1089 APP_LOGE("-n %{public}s -u %{public}d -a %{public}d parse clone resource failed",
1090 bundleName.c_str(), userId, appIndex);
1091 }
1092 // 5. add theme icon to bundleResourceIconRdb
1093 if (!bundleResourceIconRdb_->AddResourceIconInfos(userId, IconResourceType::THEME_ICON, resourceInfos)) {
1094 APP_LOGE("-n %{public}s -u %{public}d -a %{public}d add clone resource failed",
1095 bundleName.c_str(), userId, appIndex);
1096 return false;
1097 }
1098 return ret;
1099 }
1100
DeleteCloneBundleResourceInfoWhenUninstall(const std::string & bundleName,const int32_t userId,const int32_t appIndex,const bool isExistInOtherUser)1101 bool BundleResourceManager::DeleteCloneBundleResourceInfoWhenUninstall(
1102 const std::string &bundleName,
1103 const int32_t userId,
1104 const int32_t appIndex,
1105 const bool isExistInOtherUser)
1106 {
1107 /**
1108 * Need to distinguish whether bundle and appIndex exist in other users.
1109 * if not exist, need to delete both bundleResourceRdb and bundleResourceIconRdb;
1110 * if exist, only need to delete bundleResourceIconRdb.
1111 */
1112 bool ret = true;
1113 if (!isExistInOtherUser) {
1114 ResourceInfo resourceInfo;
1115 resourceInfo.bundleName_ = bundleName;
1116 resourceInfo.appIndex_ = appIndex;
1117 ret = bundleResourceRdb_->DeleteResourceInfo(resourceInfo.GetKey());
1118 if (!ret) {
1119 APP_LOGE("-n %{public}s -u %{public}d -a %{public}d delete resource failed",
1120 bundleName.c_str(), userId, appIndex);
1121 }
1122 }
1123 if (!bundleResourceIconRdb_->DeleteResourceIconInfo(bundleName, userId, appIndex)) {
1124 APP_LOGE("-n %{public}s -u %{public}d -a %{public}d delete resource failed",
1125 bundleName.c_str(), userId, appIndex);
1126 return false;
1127 }
1128 return ret;
1129 }
1130
IsNeedProcessResourceIconInfo(const uint32_t resourceFlags)1131 bool BundleResourceManager::IsNeedProcessResourceIconInfo(const uint32_t resourceFlags)
1132 {
1133 if (((resourceFlags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ALL)) ==
1134 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_ALL)) ||
1135 ((resourceFlags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON)) ==
1136 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_ICON)) ||
1137 ((resourceFlags & static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR)) ==
1138 static_cast<uint32_t>(ResourceFlag::GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR))) {
1139 return true;
1140 }
1141 return false;
1142 }
1143
GetUserId()1144 int32_t BundleResourceManager::GetUserId()
1145 {
1146 int32_t userId = BundleUtil::GetUserIdByCallingUid();
1147 if (userId == Constants::DEFAULT_USERID) {
1148 // check is sa call
1149 if (BundlePermissionMgr::IsNativeTokenType()) {
1150 userId = AccountHelper::GetCurrentActiveUserId();
1151 }
1152 }
1153 if (userId < Constants::DEFAULT_USERID) {
1154 APP_LOGE("userId %{public}d is invalid", userId);
1155 }
1156 return userId;
1157 }
1158
SetIsOnlineThemeWhenBoot()1159 void BundleResourceManager::SetIsOnlineThemeWhenBoot()
1160 {
1161 APP_LOGI("set online theme when boot start");
1162 // 1. get all user
1163 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
1164 if (dataMgr == nullptr) {
1165 APP_LOGE("dataMgr is nullptr");
1166 return;
1167 }
1168 auto userIds = dataMgr->GetAllUser();
1169 // 2. parse json file
1170 for (const auto &userId : userIds) {
1171 SetIsOnlineTheme(userId);
1172 }
1173 APP_LOGI("set online theme when boot end");
1174 }
1175
SetIsOnlineTheme(const int32_t userId)1176 void BundleResourceManager::SetIsOnlineTheme(const int32_t userId)
1177 {
1178 bool isOnlineTheme = false;
1179 if (!BundleResourceProcess::CheckThemeType("", userId, isOnlineTheme)) {
1180 APP_LOGE("userId %{public}d check online theme failed", userId);
1181 }
1182 APP_LOGI("userId %{public}d isOnlineTheme %{public}d", userId, isOnlineTheme);
1183 bundleResourceIconRdb_->SetIsOnlineTheme(userId, isOnlineTheme);
1184 }
1185
InnerProcessThemeIconWhenOta(const std::string & bundleName,const std::set<int32_t> userIds,const bool hasBundleUpdated)1186 bool BundleResourceManager::InnerProcessThemeIconWhenOta(
1187 const std::string &bundleName, const std::set<int32_t> userIds, const bool hasBundleUpdated)
1188 {
1189 // 1. theme whether exist in all user, no need to process
1190 std::vector<int32_t> existThemeUserIds;
1191 for (const auto user : userIds) {
1192 if (BundleResourceThemeProcess::IsBundleThemeExist(bundleName, user)) {
1193 existThemeUserIds.push_back(user);
1194 }
1195 }
1196 if (existThemeUserIds.empty()) {
1197 return true;
1198 }
1199 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
1200 if (dataMgr == nullptr) {
1201 APP_LOGE("dataMgr is nullptr");
1202 return false;
1203 }
1204 // 2. only process bundle resource rdb, like bundle update
1205 bool isUpdated = false;
1206 for (const auto userId : existThemeUserIds) {
1207 // bundle whether installed in user
1208 bool isInstalled = false;
1209 if ((dataMgr->IsBundleInstalled(bundleName, userId, 0, isInstalled) != ERR_OK) || !isInstalled) {
1210 continue;
1211 }
1212 if (!isUpdated && !hasBundleUpdated) {
1213 (void)AddResourceInfoByBundleNameWhenUpdate(bundleName, existThemeUserIds[0]);
1214 isUpdated = true;
1215 }
1216 (void)AddResourceInfoByBundleNameWhenCreateUser(bundleName, userId);
1217 }
1218 return true;
1219 }
1220
InnerProcessDynamicIconWhenOta(const std::string & bundleName)1221 bool BundleResourceManager::InnerProcessDynamicIconWhenOta(const std::string &bundleName)
1222 {
1223 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
1224 if (dataMgr == nullptr) {
1225 APP_LOGE("dataMgr is nullptr");
1226 return false;
1227 }
1228 // 1. check dynamic icon info, if not exist then return
1229 std::vector<DynamicIconInfo> dynamicIconInfos;
1230 if (dataMgr->GetDynamicIconInfo(bundleName, dynamicIconInfos) != ERR_OK) {
1231 APP_LOGE("get dynamic icon failed -n %{public}s", bundleName.c_str());
1232 return false;
1233 }
1234 if (dynamicIconInfos.empty()) {
1235 return true;
1236 }
1237 // 2. need parse dynamic icon, add to bundle resource icon rdb
1238 std::set<int32_t> userIds;
1239 for (const auto &dynamicIcon : dynamicIconInfos) {
1240 userIds.insert(dynamicIcon.userId);
1241 ResourceInfo resourceInfo;
1242 resourceInfo.bundleName_ = dynamicIcon.bundleName;
1243 resourceInfo.appIndex_ = dynamicIcon.appIndex;
1244 if (!BundleResourceProcess::GetDynamicIconResourceInfo(dynamicIcon.bundleName, dynamicIcon.moduleName,
1245 resourceInfo)) {
1246 APP_LOGE("get dynamic icon failed -n %{public}s", bundleName.c_str());
1247 continue;
1248 }
1249 // add bundle resource icon rdb
1250 if (!AddDynamicIconResource(bundleName, dynamicIcon.userId, dynamicIcon.appIndex, resourceInfo)) {
1251 APP_LOGE("add dynamic icon failed -n %{public}s", bundleName.c_str());
1252 }
1253 }
1254 // 3. update bundle resource rdb
1255 for (const auto userId : userIds) {
1256 if (BundleResourceThemeProcess::IsBundleThemeExist(bundleName, userId)) {
1257 if (AddResourceInfoByBundleNameWhenUpdate(bundleName, userId)) {
1258 APP_LOGE("add resource icon failed -n %{public}s -u %{public}d", bundleName.c_str(), userId);
1259 }
1260 break;
1261 }
1262 }
1263 return true;
1264 }
1265
ProcessThemeAndDynamicIconWhenOta(const std::set<std::string> & updateBundleNames)1266 bool BundleResourceManager::ProcessThemeAndDynamicIconWhenOta(
1267 const std::set<std::string> &updateBundleNames)
1268 {
1269 APP_LOGI("ProcessThemeAndDynamicIconWhenOta start");
1270 std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
1271 if (dataMgr == nullptr) {
1272 APP_LOGE("dataMgr is nullptr");
1273 return false;
1274 }
1275 PrepareSysRes();
1276 auto userIds = dataMgr->GetAllUser();
1277 // 1. get all bundle names
1278 std::vector<std::string> allBundleNames = dataMgr->GetAllBundleName();
1279 for (const auto &bundleName : allBundleNames) {
1280 // dynamic icon need all process
1281 InnerProcessDynamicIconWhenOta(bundleName);
1282 // theme icon already process when bundle update
1283 bool hasBundleUpdated = std::find(updateBundleNames.begin(), updateBundleNames.end(),
1284 bundleName) != updateBundleNames.end();
1285 InnerProcessThemeIconWhenOta(bundleName, userIds, hasBundleUpdated);
1286 }
1287 APP_LOGI("ProcessThemeAndDynamicIconWhenOta end");
1288 return true;
1289 }
1290 } // AppExecFwk
1291 } // OHOS
1292