• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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