• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include "hap_manager.h"
16 #include "hap_resource_manager.h"
17 
18 #include <algorithm>
19 #include <fstream>
20 #include <climits>
21 #include <cstdlib>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <tuple>
25 #include <set>
26 #include "utils/errors.h"
27 #ifdef SUPPORT_GRAPHICS
28 #include <ohos/init_data.h>
29 #include <unicode/unistr.h>
30 #include <unicode/utypes.h>
31 #endif
32 
33 #include "hilog_wrapper.h"
34 
35 #include "hap_parser.h"
36 #include "utils/utils.h"
37 #include "res_common.h"
38 
39 #ifdef __WINNT__
40 #include <shlwapi.h>
41 #include <windows.h>
42 #else
43 #include <dlfcn.h>
44 #endif
45 
46 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
47 #include "hitrace_meter.h"
48 #include "hisysevent_adapter.h"
49 #include "file_mapper.h"
50 #include "extractor.h"
51 #endif
52 
53 namespace OHOS {
54 namespace Global {
55 namespace Resource {
56 #ifdef SUPPORT_GRAPHICS
57 constexpr uint32_t PLURAL_CACHE_MAX_COUNT = 3;
58 #endif
59 #if defined(__ARKUI_CROSS__) || defined(__WINNT__) || defined(__IDE_PREVIEW__)
60 const std::string RAW_FILE_PATH = "resources/rawfile/";
61 #endif
62 
63 using ReadLock = std::shared_lock<std::shared_mutex>;
64 using WriteLock = std::unique_lock<std::shared_mutex>;
65 
66 std::mutex g_rawFileLock;
67 
HapManager(std::shared_ptr<ResConfigImpl> resConfig,bool isSystem)68 HapManager::HapManager(std::shared_ptr<ResConfigImpl> resConfig, bool isSystem)
69     : resConfig_(resConfig), isSystem_(isSystem)
70 {
71     overrideResConfig_->SetColorMode(COLOR_MODE_NOT_SET);
72 }
73 
HapManager(std::shared_ptr<ResConfigImpl> resConfig,std::vector<std::shared_ptr<HapResource>> hapResources,std::unordered_map<std::string,std::vector<std::string>> loadedHapPaths,bool isSystem)74 HapManager::HapManager(std::shared_ptr<ResConfigImpl> resConfig, std::vector<std::shared_ptr<HapResource>> hapResources,
75     std::unordered_map<std::string, std::vector<std::string>> loadedHapPaths, bool isSystem)
76     : resConfig_(resConfig), hapResources_(hapResources), loadedHapPaths_(loadedHapPaths), isSystem_(isSystem)
77 {
78     overrideResConfig_->SetColorMode(COLOR_MODE_NOT_SET);
79 }
80 
81 bool HapManager::icuInitialized = HapManager::Init();
82 
Init()83 bool HapManager::Init()
84 {
85 #ifdef SUPPORT_GRAPHICS
86 #ifdef __IDE_PREVIEW__
87 #ifdef __WINNT__
88     MEMORY_BASIC_INFORMATION mbi;
89     if (::VirtualQuery((LPCVOID)SetHwIcuDirectory, &mbi, sizeof(mbi)) != 0) {
90         char path[MAX_PATH] = { 0 };
91         GetModuleFileName((HMODULE)mbi.AllocationBase, path, MAX_PATH);
92         std::string tempPath(path);
93         auto pos = tempPath.rfind('\\');
94         if (pos != std::string::npos) {
95             u_setDataDirectory(tempPath.substr(0, pos).c_str());
96         }
97     }
98 #else
99     Dl_info info;
100     if (dladdr((void*)SetHwIcuDirectory, &info) != 0) {
101         std::string tempPath(info.dli_fname);
102         auto pos = tempPath.rfind('/');
103         if (pos != std::string::npos) {
104             u_setDataDirectory(tempPath.substr(0, pos).c_str());
105         }
106     }
107 #endif
108 #else
109 #if !defined(__ARKUI_CROSS__)
110     SetHwIcuDirectory();
111 #endif
112 #endif
113 #endif
114     return true;
115 }
116 
GetPluralRulesAndSelect(ResourceManager::Quantity quantity,bool isGetOverrideResource)117 std::string HapManager::GetPluralRulesAndSelect(ResourceManager::Quantity quantity, bool isGetOverrideResource)
118 {
119     std::string defaultRet("other");
120 #ifdef SUPPORT_GRAPHICS
121     WriteLock lock(this->mutex_);
122     std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isGetOverrideResource);
123     if (config == nullptr || config->GetResLocale() == nullptr ||
124         config->GetResLocale()->GetLanguage() == nullptr) {
125         RESMGR_HILOGE(RESMGR_TAG, "GetPluralRules language is null!");
126         return defaultRet;
127     }
128     std::string language = config->GetResLocale()->GetLanguage();
129 
130     icu::PluralRules *pluralRules = nullptr;
131     for (uint32_t i = 0; i < plurRulesCache_.size(); i++) {
132         auto pair = plurRulesCache_[i];
133         if (language == pair.first) {
134             // cache hit
135             pluralRules = pair.second;
136             break;
137         }
138     }
139 
140     if (pluralRules == nullptr) {
141         // no cache hit
142         icu::Locale locale(language.c_str());
143         if (locale.isBogus()) {
144             RESMGR_HILOGE(RESMGR_TAG, "icu::Locale init error : %s", language.c_str());
145             return defaultRet;
146         }
147         UErrorCode status = U_ZERO_ERROR;
148         pluralRules = icu::PluralRules::forLocale(locale, status);
149         if (status != U_ZERO_ERROR) {
150             RESMGR_HILOGE(RESMGR_TAG, "icu::PluralRules::forLocale error : %d", status);
151             return defaultRet;
152         }
153         // after PluralRules created, we add it to cache, if > 3 delete oldest one
154         if (plurRulesCache_.size() >= PLURAL_CACHE_MAX_COUNT) {
155             RESMGR_HILOGD(RESMGR_TAG, "cache rotate delete plurRulesMap_ %s", plurRulesCache_[0].first.c_str());
156             delete (plurRulesCache_[0].second);
157             plurRulesCache_.erase(plurRulesCache_.begin());
158         }
159         auto plPair = std::make_pair(language, pluralRules);
160         plurRulesCache_.push_back(plPair);
161     }
162     std::string converted;
163     icu::UnicodeString us = quantity.isInteger ? pluralRules->select(quantity.intValue) :
164         pluralRules->select(quantity.doubleValue);
165     us.toUTF8String(converted);
166     return converted;
167 #else
168     return defaultRet;
169 #endif
170 }
171 
FindResourceById(uint32_t id,bool isGetOverrideResource)172 const std::shared_ptr<IdItem> HapManager::FindResourceById(uint32_t id, bool isGetOverrideResource)
173 {
174     auto qualifierValue = FindQualifierValueById(id, isGetOverrideResource);
175     if (qualifierValue == nullptr) {
176         return nullptr;
177     }
178     return qualifierValue->GetIdItem();
179 }
180 
FindResourceByName(const char * name,const ResType resType,bool isGetOverrideResource)181 const std::shared_ptr<IdItem> HapManager::FindResourceByName(
182     const char *name, const ResType resType, bool isGetOverrideResource)
183 {
184     auto qualifierValue = FindQualifierValueByName(name, resType, isGetOverrideResource);
185     if (qualifierValue == nullptr) {
186         return nullptr;
187     }
188     return qualifierValue->GetIdItem();
189 }
190 
FindQualifierValueByName(const char * name,const ResType resType,bool isGetOverrideResource,uint32_t density)191 const std::shared_ptr<ValueUnderQualifierDir> HapManager::FindQualifierValueByName(
192     const char *name, const ResType resType, bool isGetOverrideResource, uint32_t density)
193 {
194     ReadLock lock(this->mutex_);
195     std::vector<std::shared_ptr<IdValues>> candidates = this->GetResourceListByName(name, resType);
196     if (candidates.size() == 0) {
197         return nullptr;
198     }
199     return this->GetBestMatchResource(candidates, density, isGetOverrideResource);
200 }
201 
FindQualifierValueById(uint32_t id,bool isGetOverrideResource,uint32_t density)202 const std::shared_ptr<ValueUnderQualifierDir> HapManager::FindQualifierValueById(uint32_t id,
203     bool isGetOverrideResource, uint32_t density)
204 {
205     ReadLock lock(this->mutex_);
206     std::vector<std::shared_ptr<IdValues>> candidates = this->GetResourceList(id);
207     if (candidates.size() == 0) {
208         return nullptr;
209     }
210     return this->GetBestMatchResource(candidates, density, isGetOverrideResource);
211 }
212 
getCompleteOverrideConfig(bool isGetOverrideResource)213 std::shared_ptr<ResConfigImpl> HapManager::getCompleteOverrideConfig(bool isGetOverrideResource)
214 {
215     if (!isGetOverrideResource) {
216         return this->resConfig_;
217     }
218 
219     std::shared_ptr<ResConfigImpl> completeOverrideConfig = std::make_shared<ResConfigImpl>();
220     if (!completeOverrideConfig || !this->resConfig_ || !this->overrideResConfig_) {
221         RESMGR_HILOGE(RESMGR_TAG, "completeOverrideConfig or resConfig_ or overrideResConfig_ is nullptr");
222         return nullptr;
223     }
224 
225     if (!completeOverrideConfig->Copy(*this->resConfig_, true)) {
226         RESMGR_HILOGE(RESMGR_TAG, "getCompleteOverrideConfig copy failed");
227         return nullptr;
228     }
229 
230     if (this->overrideResConfig_->isLocaleInfoSet()
231         && !completeOverrideConfig->CopyLocaleAndPreferredLocale(*this->overrideResConfig_)) {
232         RESMGR_HILOGE(RESMGR_TAG, "getCompleteOverrideConfig CopyLocaleAndPreferredLocale failed");
233         return nullptr;
234     }
235     if (this->overrideResConfig_->GetDeviceType() != DEVICE_NOT_SET) {
236         completeOverrideConfig->SetDeviceType(this->overrideResConfig_->GetDeviceType());
237     }
238     if (this->overrideResConfig_->GetDirection() != DIRECTION_NOT_SET) {
239         completeOverrideConfig->SetDirection(this->overrideResConfig_->GetDirection());
240     }
241     if (this->overrideResConfig_->GetColorMode() != COLOR_MODE_NOT_SET) {
242         completeOverrideConfig->SetColorMode(this->overrideResConfig_->GetColorMode());
243     }
244     if (this->overrideResConfig_->GetInputDevice() != INPUTDEVICE_NOT_SET) {
245         completeOverrideConfig->SetInputDevice(this->overrideResConfig_->GetInputDevice());
246     }
247     if (this->overrideResConfig_->GetMcc() != MCC_UNDEFINED) {
248         completeOverrideConfig->SetMcc(this->overrideResConfig_->GetMcc());
249     }
250     if (this->overrideResConfig_->GetMnc() != MNC_UNDEFINED) {
251         completeOverrideConfig->SetMnc(this->overrideResConfig_->GetMnc());
252     }
253     if (this->overrideResConfig_->GetScreenDensity() != SCREEN_DENSITY_NOT_SET) {
254         completeOverrideConfig->SetScreenDensity(this->overrideResConfig_->GetScreenDensity());
255     }
256     return completeOverrideConfig;
257 }
258 
MatchBestResource(std::shared_ptr<ResConfigImpl> & bestResConfig,std::shared_ptr<ValueUnderQualifierDir> & result,const std::vector<std::shared_ptr<ValueUnderQualifierDir>> & paths,uint32_t density,std::shared_ptr<ResConfigImpl> currentResConfig)259 void HapManager::MatchBestResource(std::shared_ptr<ResConfigImpl> &bestResConfig,
260     std::shared_ptr<ValueUnderQualifierDir> &result,
261     const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &paths,
262     uint32_t density, std::shared_ptr<ResConfigImpl> currentResConfig)
263 {
264     size_t len = paths.size();
265     size_t i = 0;
266     for (i = 0; i < len; i++) {
267         std::shared_ptr<ValueUnderQualifierDir> path = paths[i];
268         const auto resConfig = path->GetResConfig();
269         if (!currentResConfig->Match(resConfig)) {
270             continue;
271         }
272         if (bestResConfig == nullptr) {
273             bestResConfig = resConfig;
274             result = paths[i];
275             continue;
276         }
277         if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig, density)) {
278             bestResConfig = resConfig;
279             result = paths[i];
280         }
281     }
282 }
283 
GetBestMatchResource(const std::vector<std::shared_ptr<IdValues>> & candidates,uint32_t density,bool isGetOverrideResource)284 const std::shared_ptr<ValueUnderQualifierDir> HapManager::GetBestMatchResource(
285     const std::vector<std::shared_ptr<IdValues>> &candidates, uint32_t density, bool isGetOverrideResource)
286 {
287     std::shared_ptr<ResConfigImpl> bestResConfig = nullptr;
288     std::shared_ptr<ResConfigImpl> bestOverlayResConfig = nullptr;
289     std::shared_ptr<ValueUnderQualifierDir> result = nullptr;
290     std::shared_ptr<ValueUnderQualifierDir> overlayResult = nullptr;
291     const std::shared_ptr<ResConfigImpl> currentResConfig = getCompleteOverrideConfig(isGetOverrideResource);
292     if (!currentResConfig) {
293         return nullptr;
294     }
295     // When there are multiple overlays, reverse the search to find the first match resource.
296     for (auto iter = candidates.rbegin(); iter != candidates.rend(); iter++) {
297         const auto &paths = (*iter)->GetLimitPathsConst();
298         bool isOverlayHapResource = paths[0]->IsOverlayResource();
299         if (isOverlayHapResource) {
300             MatchBestResource(bestOverlayResConfig, overlayResult, paths, density, currentResConfig);
301         } else {
302             MatchBestResource(bestResConfig, result, paths, density, currentResConfig);
303         }
304     }
305     if (bestOverlayResConfig != nullptr && result != nullptr) {
306         if (bestOverlayResConfig->IsMoreSuitable(bestResConfig, currentResConfig, density)) {
307             return overlayResult;
308         }
309     }
310     return result;
311 }
312 
FindRawFile(const std::string & name,std::string & outValue)313 RState HapManager::FindRawFile(const std::string &name, std::string &outValue)
314 {
315 #ifdef __WINNT__
316     char seperator = '\\';
317 #else
318     char seperator = '/';
319 #endif
320     ReadLock lock(this->mutex_);
321     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
322         std::string indexPath = (*iter)->GetIndexPath();
323         auto index = indexPath.rfind(seperator);
324         if (index == std::string::npos) {
325             RESMGR_HILOGE(RESMGR_TAG, "index path format error by seperator");
326             continue;
327         }
328         std::string resourcesIndexPath = indexPath.substr(0, index);
329         char tmpPath[PATH_MAX] = {0};
330         std::string tempName = name;
331         const std::string rawFileDirName = "rawfile/";
332         if (tempName.length() <= rawFileDirName.length()
333             || (tempName.compare(0, rawFileDirName.length(), rawFileDirName) != 0)) {
334             tempName = rawFileDirName + tempName;
335         }
336 #ifdef __WINNT__
337         if (!PathCanonicalizeA(tmpPath, (resourcesIndexPath + "/resources/" + tempName).c_str())) {
338             continue;
339         }
340 #else
341         if (realpath((resourcesIndexPath + "/resources/" + tempName).c_str(), tmpPath) == nullptr) {
342             RESMGR_HILOGE(RESMGR_TAG, "FindRawFile path to realpath error");
343             continue;
344         }
345 #endif
346         const std::string realPath = tmpPath;
347         std::fstream inputFile;
348         inputFile.open(realPath, std::ios::in);
349         if (inputFile) {
350             outValue = realPath;
351             inputFile.close();
352             return SUCCESS;
353         }
354     }
355     return ERROR_CODE_RES_PATH_INVALID;
356 }
357 
UpdateResConfig(ResConfig & resConfig)358 RState HapManager::UpdateResConfig(ResConfig &resConfig)
359 {
360     WriteLock lock(this->mutex_);
361     bool needUpdate = !this->resConfig_->MatchLocal(resConfig);
362     this->resConfig_->Copy(resConfig);
363     if (needUpdate) {
364         for (auto &resource : hapResources_) {
365             RState state = resource->Update(this->resConfig_);
366             if (state != SUCCESS) {
367                 return state;
368             }
369         }
370     }
371     return SUCCESS;
372 }
373 
UpdateOverrideResConfig(ResConfig & resConfig)374 RState HapManager::UpdateOverrideResConfig(ResConfig &resConfig)
375 {
376     WriteLock lock(this->mutex_);
377     bool needUpdate = !this->overrideResConfig_->MatchLocal(resConfig);
378     this->overrideResConfig_->Copy(resConfig);
379     if (needUpdate) {
380         for (auto &resource : hapResources_) {
381             RState state = resource->Update(this->overrideResConfig_);
382             if (state != SUCCESS) {
383                 return state;
384             }
385         }
386     }
387     return SUCCESS;
388 }
389 
GetResConfig(ResConfig & resConfig)390 void HapManager::GetResConfig(ResConfig &resConfig)
391 {
392     ReadLock lock(this->mutex_);
393     resConfig.Copy(*(this->resConfig_), true);
394 }
395 
GetResConfigById(uint32_t resId,ResConfig & resConfig,bool isGetOverrideResource,uint32_t density)396 RState HapManager::GetResConfigById(uint32_t resId, ResConfig &resConfig, bool isGetOverrideResource, uint32_t density)
397 {
398     auto qualifierValue = FindQualifierValueById(resId, isGetOverrideResource, density);
399     if (qualifierValue == nullptr) {
400         return ERROR_CODE_RES_NOT_FOUND_BY_ID;
401     }
402     resConfig.Copy(*(qualifierValue->GetResConfig()), true);
403     return SUCCESS;
404 }
405 
GetResConfigByName(const std::string & name,const ResType type,ResConfig & resConfig,bool isGetOverrideResource,uint32_t density)406 RState HapManager::GetResConfigByName(const std::string &name, const ResType type, ResConfig &resConfig,
407     bool isGetOverrideResource, uint32_t density)
408 {
409     auto qualifierValue = FindQualifierValueByName(name.c_str(), type, isGetOverrideResource, density);
410     if (qualifierValue == nullptr) {
411         return ERROR_CODE_RES_NOT_FOUND_BY_NAME;
412     }
413     resConfig.Copy(*(qualifierValue->GetResConfig()), true);
414     return SUCCESS;
415 }
416 
GetOverrideResConfig(ResConfig & resConfig)417 void HapManager::GetOverrideResConfig(ResConfig &resConfig)
418 {
419     ReadLock lock(this->mutex_);
420     resConfig.Copy(*(this->overrideResConfig_));
421 }
422 
AddResource(const char * path,const uint32_t & selectedTypes,bool forceReload)423 bool HapManager::AddResource(const char *path, const uint32_t &selectedTypes, bool forceReload)
424 {
425     WriteLock lock(this->mutex_);
426     std::string sPath(path);
427 #if defined(__ARKUI_CROSS__)
428     if (forceReload) {
429         HapResourceManager::GetInstance().RemoveHapResource(sPath);
430         RemoveHapResource(sPath);
431     }
432 #endif
433     auto it = loadedHapPaths_.find(sPath);
434     if (it != loadedHapPaths_.end()) {
435         return false;
436     }
437     std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
438     std::shared_ptr<HapResource> pResource =
439         HapResourceManager::GetInstance().Load(path, config, isSystem_, false, selectedTypes);
440     if (pResource == nullptr) {
441         return false;
442     }
443     this->loadedHapPaths_[sPath] = std::vector<std::string>();
444     this->hapResources_.push_back(pResource);
445     if (pResource->HasDarkRes()) {
446         this->resConfig_->SetAppDarkRes(true);
447     }
448     if (!pResource->IsSystemResource() && !pResource->IsOverlayResource()
449         && pResource->IsThemeSystemResEnable()) {
450         this->isThemeSystemResEnable_ = true;
451     }
452     return true;
453 }
454 
AddPatchResource(const char * path,const char * patchPath)455 bool HapManager::AddPatchResource(const char *path, const char *patchPath)
456 {
457     WriteLock lock(this->mutex_);
458     std::string sPath(path);
459     auto it = loadedHapPaths_.find(sPath);
460     if (it == loadedHapPaths_.end()) {
461         RESMGR_HILOGW(RESMGR_TAG, "AddPatchResource hapPath not load");
462         return false;
463     }
464     std::string sPatchPath(patchPath);
465     return HapResourceManager::GetInstance().PutPatchResource(sPath, sPatchPath);
466 }
467 
AddResource(const std::string & path,const std::vector<std::string> & overlayPaths)468 bool HapManager::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
469 {
470     WriteLock lock(this->mutex_);
471     std::vector<std::string> targetOverlay = loadedHapPaths_[path];
472     if (!targetOverlay.empty() && targetOverlay == overlayPaths) {
473         RESMGR_HILOGI(RESMGR_TAG, "the overlay hap already been loaded");
474         return true;
475     }
476     std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
477     std::unordered_map<std::string, std::shared_ptr<HapResource>> result =
478         HapResourceManager::GetInstance().LoadOverlays(path, overlayPaths, config, isSystem_);
479     if (result.size() == 0) {
480         return false;
481     }
482     if (result.find(path) != result.end()) {
483         hapResources_.push_back(result[path]);
484         if (result[path]->HasDarkRes()) {
485             this->resConfig_->SetAppDarkRes(true);
486         }
487         if (!result[path]->IsSystemResource() && !result[path]->IsOverlayResource()
488             && result[path]->IsThemeSystemResEnable()) {
489             this->isThemeSystemResEnable_ = true;
490         }
491     }
492     for (auto iter = overlayPaths.rbegin(); iter != overlayPaths.rend(); iter++) {
493         if (result.find(*iter) != result.end()) {
494             hapResources_.push_back(result[*iter]);
495         }
496     }
497     loadedHapPaths_[path] = overlayPaths;
498     return true;
499 }
500 
GetValidAppPath()501 std::string HapManager::GetValidAppPath()
502 {
503     std::string appPath;
504     ReadLock lock(this->mutex_);
505     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
506         const std::string tempPath = (*iter)->GetIndexPath();
507         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
508             continue;
509         }
510         appPath = tempPath;
511     }
512     return appPath;
513 }
514 
AddAppOverlay(const std::string & overlayPath)515 bool HapManager::AddAppOverlay(const std::string &overlayPath)
516 {
517     char outPath[PATH_MAX + 1] = {0};
518     Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
519     if (outPath[0] == '\0') {
520         RESMGR_HILOGE(RESMGR_TAG, "AddAppOverlay invalid overlayPath");
521         return false;
522     }
523     std::vector<std::string> overlayPaths;
524     overlayPaths.emplace_back(outPath);
525     std::string appPath = GetValidAppPath();
526     return AddResource(appPath, overlayPaths);
527 }
528 
RemoveAppOverlay(const std::string & overlayPath)529 bool HapManager::RemoveAppOverlay(const std::string &overlayPath)
530 {
531     char outPath[PATH_MAX + 1] = {0};
532     Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
533     if (outPath[0] == '\0') {
534         RESMGR_HILOGE(RESMGR_TAG, "RemoveAppOverlay invalid overlayPath");
535         return false;
536     }
537     std::vector<std::string> overlayPaths;
538     overlayPaths.emplace_back(outPath);
539     std::string appPath = GetValidAppPath();
540     return RemoveResource(appPath, overlayPaths);
541 }
542 
~HapManager()543 HapManager::~HapManager()
544 {
545 #ifndef SUPPORT_ASAN
546     WriteLock lock(this->mutex_);
547     hapResources_.clear();
548     loadedHapPaths_.clear();
549 #endif
550 
551 #ifdef SUPPORT_GRAPHICS
552     auto iter = plurRulesCache_.begin();
553     for (; iter != plurRulesCache_.end(); iter++) {
554         RESMGR_HILOGD(RESMGR_TAG, "delete plurRulesMap_ %s", iter->first.c_str());
555         if (iter->second != nullptr) {
556             auto ptr = iter->second;
557             delete (ptr);
558             iter->second = nullptr;
559         }
560     }
561 #endif
562 }
563 
GetResourceList(uint32_t ident) const564 std::vector<std::shared_ptr<IdValues>> HapManager::GetResourceList(uint32_t ident) const
565 {
566     std::vector<std::shared_ptr<IdValues>> result;
567     // one id only exit in one hap
568     for (size_t i = 0; i < hapResources_.size(); ++i) {
569         std::shared_ptr<HapResource> pResource = hapResources_[i];
570         const std::shared_ptr<IdValues> out = pResource->GetIdValues(ident);
571         if (out != nullptr) {
572             result.emplace_back(out);
573         }
574     }
575     return result;
576 }
577 
GetResourceListByName(const char * name,const ResType resType) const578 std::vector<std::shared_ptr<IdValues>> HapManager::GetResourceListByName(const char *name,
579     const ResType resType) const
580 {
581     std::vector<std::shared_ptr<IdValues>> result;
582     // all match will return
583     if (name == nullptr) {
584         return result;
585     }
586     std::string key(name);
587     for (size_t i = 0; i < hapResources_.size(); ++i) {
588         std::shared_ptr<HapResource> pResource = hapResources_[i];
589         const std::shared_ptr<IdValues> out = pResource->GetIdValuesByName(key, resType);
590         if (out != nullptr) {
591             result.emplace_back(out);
592         }
593     }
594     return result;
595 }
596 
597 #if defined(__ARKUI_CROSS__)
RemoveHapResource(const std::string & path)598 void HapManager::RemoveHapResource(const std::string &path)
599 {
600     for (auto iter = hapResources_.begin(); iter != hapResources_.end();) {
601         if ((*iter)->GetIndexPath() == path) {
602             iter = hapResources_.erase(iter);
603             break;
604         } else {
605             ++iter;
606         }
607     }
608 
609     auto it = loadedHapPaths_.find(path);
610     if (it != loadedHapPaths_.end()) {
611         loadedHapPaths_.erase(it);
612     }
613 }
614 #endif
615 
GetResourcePaths()616 std::vector<std::string> HapManager::GetResourcePaths()
617 {
618     std::vector<std::string> result;
619     ReadLock lock(this->mutex_);
620     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
621         std::string indexPath = (*iter)->GetIndexPath();
622         auto index = indexPath.rfind('/');
623         if (index == std::string::npos) {
624             RESMGR_HILOGE(RESMGR_TAG, "index path format error");
625             continue;
626         }
627 
628         result.emplace_back(indexPath.substr(0, index) + "/resources/");
629     }
630 
631     return result;
632 }
633 
GetImageType(const std::string fileName)634 std::string GetImageType(const std::string fileName)
635 {
636     auto pos = fileName.find_last_of('.');
637     std::string imgType;
638     if (pos != std::string::npos) {
639         imgType = fileName.substr(pos + 1);
640     }
641     return imgType;
642 }
643 
644 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> & extractor,const std::shared_ptr<ValueUnderQualifierDir> qd,const ResType resType)645 std::string GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> &extractor,
646     const std::shared_ptr<ValueUnderQualifierDir> qd, const ResType resType)
647 {
648     std::string filePath;
649     if (qd == nullptr) {
650         RESMGR_HILOGE(RESMGR_TAG, "GetFilePathFromHap qd is null");
651         return filePath;
652     }
653     const std::shared_ptr<IdItem> idItem = qd->GetIdItem();
654     if (idItem == nullptr || idItem->resType_ != resType) {
655         std::string hapPath = qd->GetIndexPath();
656         RESMGR_HILOGE(RESMGR_TAG, "actual resType = %{public}d, expect resType = %{public}d",
657             idItem == nullptr ? -1 : idItem->resType_, resType);
658         return filePath;
659     }
660     if (extractor->IsStageModel()) {
661         std::string tempFilePath(idItem->value_);
662         auto index = tempFilePath.find('/');
663         if (index == std::string::npos) {
664             RESMGR_HILOGE(RESMGR_TAG, "resource path format error");
665             return filePath;
666         }
667         filePath = idItem->value_.substr(index + 1);
668     } else {
669         // FA mode
670         std::string tempFilePath("assets/");
671         tempFilePath.append(idItem->value_);
672         filePath = tempFilePath;
673     }
674     return filePath;
675 }
676 #endif
677 
678 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetAbilityExtractor(const std::shared_ptr<ValueUnderQualifierDir> qd)679 std::shared_ptr<AbilityBase::Extractor> GetAbilityExtractor(
680     const std::shared_ptr<ValueUnderQualifierDir> qd)
681 {
682     std::string hapPath = qd->GetIndexPath();
683     bool isNewExtractor = false;
684     auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
685     return extractor;
686 }
687 #endif
688 
GetProfileData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)689 RState HapManager::GetProfileData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
690     std::unique_ptr<uint8_t[]> &outValue)
691 {
692 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
693     auto extractor = GetAbilityExtractor(qualifierDir);
694     if (extractor == nullptr) {
695         RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
696         return NOT_FOUND;
697     }
698     std::string filePath = GetFilePathFromHap(extractor, qualifierDir, ResType::PROF);
699     if (filePath.empty()) {
700         RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetProfileData");
701         return NOT_FOUND;
702     }
703     bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
704     if (!ret) {
705         RESMGR_HILOGE(RESMGR_TAG, "failed to get config data from ability");
706         return NOT_FOUND;
707     }
708 #endif
709     return SUCCESS;
710 }
711 
GetMediaData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)712 RState HapManager::GetMediaData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
713     std::unique_ptr<uint8_t[]> &outValue)
714 {
715     std::string filePath = qualifierDir->GetIndexPath();
716     RState state;
717     if (Utils::ContainsTail(filePath, Utils::tailSet)) {
718         state = HapManager::GetMediaDataFromHap(qualifierDir, len, outValue);
719     } else {
720         state = HapManager::GetMediaDataFromIndex(qualifierDir, len, outValue);
721     }
722     return state;
723 }
724 
GetMediaDataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)725 RState HapManager::GetMediaDataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
726     std::unique_ptr<uint8_t[]> &outValue)
727 {
728 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
729     HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
730     auto extractor = GetAbilityExtractor(qualifierDir);
731     if (extractor == nullptr) {
732         RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
733         return NOT_FOUND;
734     }
735     std::string filePath = GetFilePathFromHap(extractor, qualifierDir, ResType::MEDIA);
736     if (filePath.empty()) {
737         RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetMediaDataFromHap");
738         return NOT_FOUND;
739     }
740     bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
741     if (!ret) {
742         RESMGR_HILOGE(RESMGR_TAG, "failed to get media data from ability");
743         return NOT_FOUND;
744     }
745 #endif
746     return SUCCESS;
747 }
748 
GetMediaDataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)749 RState HapManager::GetMediaDataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
750     std::unique_ptr<uint8_t[]> &outValue)
751 {
752     std::string filePath;
753     RState state = HapManager::GetFilePath(qualifierDir, ResType::MEDIA, filePath);
754     if (state != SUCCESS) {
755         return NOT_FOUND;
756     }
757     outValue = Utils::LoadResourceFile(filePath, len);
758     return SUCCESS;
759 }
760 
GetMediaBase64Data(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,std::string & outValue)761 RState HapManager::GetMediaBase64Data(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,
762     std::string &outValue)
763 {
764     std::string filePath = qualifierDir->GetIndexPath();
765     RState state;
766     if (Utils::ContainsTail(filePath, Utils::tailSet)) {
767         state = HapManager::GetMediaBase64DataFromHap(qualifierDir, outValue);
768     } else {
769         state = HapManager::GetMediaBase64DataFromIndex(qualifierDir, outValue);
770     }
771     return state;
772 }
773 
GetMediaBase64DataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,std::string & outValue)774 RState HapManager::GetMediaBase64DataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,
775     std::string &outValue)
776 {
777 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
778     auto extractor = GetAbilityExtractor(qualifierDir);
779     if (extractor == nullptr) {
780         RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
781         return NOT_FOUND;
782     }
783     std::string filePath = GetFilePathFromHap(extractor, qualifierDir, ResType::MEDIA);
784     std::unique_ptr<uint8_t[]> buffer;
785     size_t tmpLen;
786     bool ret = extractor->ExtractToBufByName(filePath, buffer, tmpLen);
787     if (!ret) {
788         RESMGR_HILOGE(RESMGR_TAG, "failed to get mediabase64 data from ability");
789         return NOT_FOUND;
790     }
791     std::string imgType = GetImageType(filePath);
792     Utils::EncodeBase64(buffer, tmpLen, imgType, outValue);
793 #endif
794     return SUCCESS;
795 }
796 
GetMediaBase64DataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,std::string & outValue)797 RState HapManager::GetMediaBase64DataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,
798     std::string &outValue)
799 {
800     std::string filePath;
801     RState state = HapManager::GetFilePath(qualifierDir, ResType::MEDIA, filePath);
802     if (state != SUCCESS) {
803         return NOT_FOUND;
804     }
805     return Utils::GetMediaBase64Data(filePath, outValue);
806 }
807 
GetValidHapPath(std::string & hapPath)808 int32_t HapManager::GetValidHapPath(std::string &hapPath)
809 {
810     ReadLock lock(this->mutex_);
811     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
812         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
813             continue;
814         }
815         const std::string tempPath = (*iter)->GetIndexPath();
816         if (Utils::ContainsTail(tempPath, Utils::tailSet)) {
817             hapPath = tempPath;
818             return OK;
819         }
820     }
821     return NOT_FOUND;
822 }
823 
GetValidResourceIndexPath(std::string & indexPath)824 int32_t HapManager::GetValidResourceIndexPath(std::string &indexPath)
825 {
826     ReadLock lock(this->mutex_);
827     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
828         const std::string tempPath = (*iter)->GetIndexPath();
829         if (Utils::IsSystemPath(tempPath)) {
830             continue;
831         }
832         indexPath = tempPath;
833         return OK;
834     }
835     return NOT_FOUND;
836 }
837 
FindRawFileFromHap(const std::string & rawFileName,size_t & len,std::unique_ptr<uint8_t[]> & outValue)838 RState HapManager::FindRawFileFromHap(const std::string &rawFileName, size_t &len,
839     std::unique_ptr<uint8_t[]> &outValue)
840 {
841     ReadLock lock(this->mutex_);
842     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
843         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
844             continue;
845         }
846         std::string tempPath = (*iter)->GetIndexPath();
847         std::string tempPatchPath;
848         if ((*iter)->HasPatch()) {
849             tempPatchPath = (*iter)->GetPatchPath();
850         }
851         if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
852             RState state = HapParser::ReadRawFileFromHap(tempPath, tempPatchPath, rawFileName, len, outValue);
853             if (state != SUCCESS) {
854                 continue;
855             }
856         } else { // if file path is uncompressed
857             std::string filePath;
858             HapManager::FindRawFile(rawFileName, filePath);
859             outValue = Utils::LoadResourceFile(filePath, len);
860             if (outValue == nullptr) {
861                 continue;
862             }
863         }
864         return SUCCESS;
865     }
866     return ERROR_CODE_RES_PATH_INVALID;
867 }
868 
FindRawFileDescriptorFromHap(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)869 RState HapManager::FindRawFileDescriptorFromHap(const std::string &rawFileName,
870     ResourceManager::RawFileDescriptor &descriptor)
871 {
872     std::lock_guard<std::mutex> lock(g_rawFileLock);
873     auto it = rawFileDescriptor_.find(rawFileName);
874     if (it != rawFileDescriptor_.end()) {
875         descriptor.fd = rawFileDescriptor_[rawFileName].fd;
876         descriptor.length = rawFileDescriptor_[rawFileName].length;
877         descriptor.offset = rawFileDescriptor_[rawFileName].offset;
878         return SUCCESS;
879     }
880     RState state = GetRawFd(rawFileName, descriptor);
881     if (state == SUCCESS) {
882         rawFileDescriptor_[rawFileName] = descriptor;
883     }
884     return state;
885 }
886 
GetRawFd(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)887 RState HapManager::GetRawFd(const std::string &rawFileName, ResourceManager::RawFileDescriptor &descriptor)
888 {
889     RState state;
890     ReadLock lock(this->mutex_);
891     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
892         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
893             continue;
894         }
895         std::string tempPath = (*iter)->GetIndexPath();
896         std::string tempPatchPath;
897         if ((*iter)->HasPatch()) {
898             tempPatchPath = (*iter)->GetPatchPath();
899         }
900         if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
901             state = HapParser::ReadRawFileDescriptor(tempPath.c_str(), tempPatchPath.c_str(), rawFileName, descriptor);
902         } else { // if file path is uncompressed
903             state = HapManager::FindRawFileDescriptor(rawFileName, descriptor);
904         }
905         if (state != SUCCESS) {
906             continue;
907         }
908         return SUCCESS;
909     }
910     return ERROR_CODE_RES_PATH_INVALID;
911 }
912 
GetRawFileList(const std::string & rawDirPath,std::vector<std::string> & fileList)913 RState HapManager::GetRawFileList(const std::string &rawDirPath, std::vector<std::string> &fileList)
914 {
915     std::string hapOrIndexPath;
916     if (HapManager::GetValidHapPath(hapOrIndexPath) == OK) {
917         std::string temPatchPath;
918         {
919             ReadLock lock(this->mutex_);
920             for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
921                 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
922                     continue;
923                 }
924                 if ((*iter)->GetIndexPath() == hapOrIndexPath && (*iter)->HasPatch()) {
925                     temPatchPath = (*iter)->GetPatchPath();
926                 }
927             }
928         }
929         std::set<std::string> fileSet;
930         RState hapState = HapParser::GetRawFileList(hapOrIndexPath, rawDirPath, fileSet);
931         RState hqfState = NOT_FOUND;
932         if (!temPatchPath.empty()) {
933             hqfState = HapParser::GetRawFileList(temPatchPath, rawDirPath, fileSet);
934         }
935         for (auto it = fileSet.begin(); it != fileSet.end(); it++) {
936             fileList.emplace_back(*it);
937         }
938         return (hapState != SUCCESS && hqfState != SUCCESS) ? ERROR_CODE_RES_PATH_INVALID : SUCCESS;
939     }
940     if (HapManager::GetValidResourceIndexPath(hapOrIndexPath) == OK) {
941         return  HapParser::GetRawFileListUnCompressed(hapOrIndexPath, rawDirPath, fileList);
942     }
943     return ERROR_CODE_RES_PATH_INVALID;
944 }
945 
IsLoadHap(std::string & hapPath)946 bool HapManager::IsLoadHap(std::string &hapPath)
947 {
948     return HapManager::GetValidHapPath(hapPath) == OK ? true : false;
949 }
950 
GetFilePath(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,const ResType resType,std::string & outValue)951 RState HapManager::GetFilePath(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, const ResType resType,
952     std::string &outValue)
953 {
954     // not found or type invalid
955     if (qualifierDir == nullptr) {
956         return NOT_FOUND;
957     }
958     const std::shared_ptr<IdItem> idItem = qualifierDir->GetIdItem();
959     if (idItem == nullptr || idItem->resType_ != resType) {
960         return NOT_FOUND;
961     }
962     outValue = qualifierDir->GetResourcePath();
963 #if defined(__ARKUI_CROSS__)
964     auto index = idItem->value_.find('/');
965     if (index == std::string::npos) {
966         RESMGR_HILOGE(RESMGR_TAG, "resource path format error");
967         return NOT_FOUND;
968     }
969     auto nameWithoutModule = idItem->value_.substr(index + 1);
970     outValue.append(nameWithoutModule);
971 #elif defined(__IDE_PREVIEW__)
972     if (Utils::IsFileExist(idItem->value_)) {
973         outValue = idItem->value_;
974         return SUCCESS;
975     }
976     auto index = idItem->value_.find('/');
977     if (index == std::string::npos) {
978         RESMGR_HILOGE(RESMGR_TAG, "resource path format error");
979         return NOT_FOUND;
980     }
981     auto nameWithoutModule = idItem->value_.substr(index + 1);
982     outValue.append(nameWithoutModule);
983 #else
984     outValue.append(idItem->value_);
985 #endif
986     return SUCCESS;
987 }
988 
FindRawFileDescriptor(const std::string & name,ResourceManager::RawFileDescriptor & descriptor)989 RState HapManager::FindRawFileDescriptor(const std::string &name, ResourceManager::RawFileDescriptor &descriptor)
990 {
991     std::string paths = "";
992     RState rState = HapManager::FindRawFile(name, paths);
993     if (rState != SUCCESS) {
994         return rState;
995     }
996     char outPath[PATH_MAX + 1] = {0};
997     Utils::CanonicalizePath(paths.c_str(), outPath, PATH_MAX);
998     int fd = open(outPath, O_RDONLY);
999     if (fd > 0) {
1000         long length = lseek(fd, 0, SEEK_END);
1001         if (length == -1) {
1002             close(fd);
1003             return ERROR_CODE_RES_PATH_INVALID;
1004         }
1005         long begin = lseek(fd, 0, SEEK_SET);
1006         if (begin == -1) {
1007             close(fd);
1008             return ERROR_CODE_RES_PATH_INVALID;
1009         }
1010         descriptor.fd = fd;
1011         descriptor.length = length;
1012         descriptor.offset = 0;
1013         return SUCCESS;
1014     }
1015     return ERROR_CODE_RES_PATH_INVALID;
1016 }
1017 
CloseRawFileDescriptor(const std::string & name)1018 RState HapManager::CloseRawFileDescriptor(const std::string &name)
1019 {
1020     std::lock_guard<std::mutex> lock(g_rawFileLock);
1021     auto it = rawFileDescriptor_.find(name);
1022     if (it == rawFileDescriptor_.end()) {
1023         return ERROR_CODE_RES_PATH_INVALID;
1024     }
1025 
1026     int fd = rawFileDescriptor_[name].fd;
1027     if (fd <= 0) {
1028         return ERROR_CODE_RES_PATH_INVALID;
1029     }
1030 
1031 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
1032     if (fdsan_get_owner_tag(fd) != 0) {
1033         rawFileDescriptor_.erase(name);
1034         return SUCCESS;
1035     }
1036 #endif
1037 
1038     if (close(fd) == -1) {
1039         return ERROR_CODE_RES_PATH_INVALID;
1040     }
1041 
1042     rawFileDescriptor_.erase(name);
1043     return SUCCESS;
1044 }
1045 
RemoveResource(const std::string & path,const std::vector<std::string> & overlayPaths)1046 bool HapManager::RemoveResource(const std::string &path, const std::vector<std::string> &overlayPaths)
1047 {
1048     WriteLock lock(this->mutex_);
1049     if (loadedHapPaths_.find(path) == loadedHapPaths_.end()) {
1050         return false;
1051     }
1052     std::vector<std::string> targetOverlay = loadedHapPaths_[path];
1053     if (targetOverlay.empty()) {
1054         RESMGR_HILOGE(RESMGR_TAG, "the hap have not overlay");
1055         return false;
1056     }
1057     char outPath[PATH_MAX] = {0};
1058     for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
1059         Utils::CanonicalizePath((*iter).c_str(), outPath, PATH_MAX);
1060         if (outPath[0] == '\0') {
1061             RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath");
1062             continue;
1063         }
1064         if (std::find(targetOverlay.begin(), targetOverlay.end(), outPath) != targetOverlay.end()) {
1065             targetOverlay.erase(std::remove(targetOverlay.begin(), targetOverlay.end(), outPath),
1066                 targetOverlay.end());
1067         }
1068         for (auto resIter = hapResources_.begin(); resIter != hapResources_.end();) {
1069             if ((*resIter) == nullptr) {
1070                 RESMGR_HILOGE(RESMGR_TAG, "hapResource is nullptr");
1071                 return false;
1072             }
1073             std::string hapPath = (*resIter)->GetIndexPath();
1074             if (hapPath == outPath) {
1075                 resIter = hapResources_.erase(resIter);
1076             } else {
1077                 resIter++;
1078             }
1079         }
1080     }
1081     loadedHapPaths_[path] = targetOverlay;
1082     return true;
1083 }
1084 
GetHapResource()1085 std::vector<std::shared_ptr<HapResource>> HapManager::GetHapResource()
1086 {
1087     return hapResources_;
1088 }
1089 
AddSystemResource(const std::shared_ptr<HapManager> & systemHapManager)1090 void HapManager::AddSystemResource(const std::shared_ptr<HapManager> &systemHapManager)
1091 {
1092     if (systemHapManager == nullptr) {
1093         RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, systemHapManager is nullptr");
1094         return;
1095     }
1096     if (!systemHapManager->isSystem_) {
1097         RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, the added hapManager is not system");
1098         return;
1099     }
1100     WriteLock lock(this->mutex_);
1101     // add system resource to app resource vector
1102     const std::vector<std::shared_ptr<HapResource>> &systemResources = systemHapManager->hapResources_;
1103     for (size_t i = 0; i < systemResources.size(); i++) {
1104         this->hapResources_.push_back(systemResources[i]);
1105     }
1106 
1107     // add system loaded path to app loaded path map.
1108     const std::unordered_map<std::string, std::vector<std::string>> &loadedSystemPaths =
1109         systemHapManager->loadedHapPaths_;
1110     for (auto iter = loadedSystemPaths.begin(); iter != loadedSystemPaths.end(); iter++) {
1111         const std::vector<std::string> &overlayPaths = iter->second;
1112         if (this->loadedHapPaths_.find(iter->first) == this->loadedHapPaths_.end()) {
1113             this->loadedHapPaths_[iter->first] = overlayPaths;
1114         }
1115     }
1116 }
1117 
GetResourceLimitKeys()1118 uint32_t HapManager::GetResourceLimitKeys()
1119 {
1120     ReadLock lock(this->mutex_);
1121     uint32_t limitKeysValue = 0;
1122     for (size_t i = 0; i < hapResources_.size(); i++) {
1123         limitKeysValue |= hapResources_[i]->GetLimitKeysValue();
1124     }
1125     RESMGR_HILOGD(RESMGR_TAG, "hap manager limit key is %{public}u", limitKeysValue);
1126     return limitKeysValue;
1127 }
1128 
1129 std::unordered_map<std::string, ResType> ResTypeMap {
1130     {"integer", INTEGER},
1131     {"string", STRING},
1132     {"strarray", STRINGARRAY},
1133     {"intarray", INTARRAY},
1134     {"boolean", BOOLEAN},
1135     {"color", COLOR},
1136     {"theme", THEME},
1137     {"plural", PLURALS},
1138     {"float", FLOAT},
1139     {"media", MEDIA},
1140     {"profile", PROF},
1141     {"pattern", PATTERN},
1142     {"symbol", SYMBOL},
1143 };
1144 
IsPrefix(std::string_view prefix,std::string_view full)1145 bool IsPrefix(std::string_view prefix, std::string_view full)
1146 {
1147     return prefix == full.substr(0, prefix.size());
1148 }
1149 
GetRealResId(const std::string & resType,const std::vector<std::unordered_map<ResType,uint32_t>> & candidates)1150 uint32_t GetRealResId(const std::string &resType,
1151     const std::vector<std::unordered_map<ResType, uint32_t>> &candidates)
1152 {
1153     for (auto candidate : candidates) {
1154         for (auto data : candidate) {
1155             if (ResTypeMap.find(resType) != ResTypeMap.end() && ResTypeMap[resType] == data.first) {
1156                 return data.second;
1157             }
1158         }
1159     }
1160     return 0;
1161 }
1162 
GetResTypeAndResName(const std::string & resTypeName)1163 std::tuple<std::string, std::string> GetResTypeAndResName(const std::string &resTypeName)
1164 {
1165     std::tuple<std::string, std::string> typeNameTuple;
1166     auto pos1 = resTypeName.find('.');
1167     auto pos2 = resTypeName.rfind('.');
1168     if (pos1 == std::string::npos || pos2 == std::string::npos) {
1169         return std::make_tuple("", "");
1170     }
1171     if (pos2 < pos1 + 1) {
1172         return std::make_tuple("", "");
1173     }
1174     const std::string resType = resTypeName.substr(pos1 + 1, pos2 - pos1 - 1);
1175     if (ResTypeMap.find(resType) == ResTypeMap.end()) {
1176         return std::make_tuple("", "");
1177     }
1178     const std::string resName = resTypeName.substr(pos2 + 1);
1179     if (resName.empty()) {
1180         return std::make_tuple("", "");
1181     }
1182     typeNameTuple = std::make_tuple(resType, resName);
1183     return typeNameTuple;
1184 }
1185 
GetResId(const std::string & resTypeName,uint32_t & resId)1186 RState HapManager::GetResId(const std::string &resTypeName, uint32_t &resId)
1187 {
1188     auto typeNameTuple = GetResTypeAndResName(resTypeName);
1189     const std::string resType =  std::get<0>(typeNameTuple);
1190     const std::string resName =  std::get<1>(typeNameTuple);
1191     if (resType.empty() || resName.empty()) {
1192         RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1193         return NOT_FOUND;
1194     }
1195     bool isSystem = IsPrefix("sys", resTypeName);
1196     bool isApp = IsPrefix("app", resTypeName);
1197     if (!isSystem && !isApp) {
1198         RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1199         return NOT_FOUND;
1200     }
1201     ReadLock lock(this->mutex_);
1202     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1203         bool isSystemResource = (*iter)->IsSystemResource();
1204         bool isOverlayResource = (*iter)->IsOverlayResource();
1205         if (isOverlayResource) {
1206             continue;
1207         }
1208         if (isSystem && !isSystemResource) {
1209             continue;
1210         }
1211         if (isApp && isSystemResource) {
1212             continue;
1213         }
1214         std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> nameTypeIdMap =
1215                 (*iter)->BuildNameTypeIdMapping();
1216         std::vector<std::unordered_map<ResType, uint32_t>> candidates;
1217         for (auto data : nameTypeIdMap) {
1218             if (data.first != resName) {
1219                 continue;
1220             }
1221             candidates.emplace_back(data.second);
1222         }
1223         resId = GetRealResId(resType, candidates);
1224         if (resId != 0) {
1225             return SUCCESS;
1226         }
1227     }
1228     if (resId == 0) {
1229         RESMGR_HILOGE(RESMGR_TAG, "GetResId name:%{public}s, resType:%{public}s", resName.c_str(), resType.c_str());
1230     }
1231     return NOT_FOUND;
1232 }
1233 
GetLocales(std::vector<std::string> & outValue,bool includeSystem)1234 void HapManager::GetLocales(std::vector<std::string> &outValue, bool includeSystem)
1235 {
1236     if (isSystem_) {
1237         includeSystem = true;
1238     }
1239     std::set<std::string> result;
1240     ReadLock lock(this->mutex_);
1241     for (size_t i = 0; i < hapResources_.size(); i++) {
1242         hapResources_[i]->GetLocales(result, includeSystem);
1243     }
1244     outValue.assign(result.begin(), result.end());
1245 }
1246 
IsRawDirFromHap(const std::string & pathName,bool & outValue)1247 RState HapManager::IsRawDirFromHap(const std::string &pathName, bool &outValue)
1248 {
1249     ReadLock lock(this->mutex_);
1250     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1251         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
1252             continue;
1253         }
1254         const std::string tempPath = (*iter)->GetIndexPath();
1255         if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
1256             RState state = HapParser::IsRawDirFromHap(tempPath.c_str(), pathName, outValue);
1257             if (state != SUCCESS) {
1258                 continue;
1259             }
1260         } else { // if file path is uncompressed
1261 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
1262             RState state = HapParser::IsRawDirUnCompressed(pathName, outValue);
1263             if (state != SUCCESS) {
1264                 continue;
1265             }
1266 #else
1267             const std::string finalPath = (*iter)->GetResourcePath() + RAW_FILE_PATH + pathName;
1268             RState state = HapParser::IsRawDirUnCompressed(finalPath, outValue);
1269             if (state != SUCCESS) {
1270                 continue;
1271             }
1272 #endif
1273         }
1274         return SUCCESS;
1275     }
1276     return ERROR_CODE_RES_PATH_INVALID;
1277 }
1278 
IsThemeSystemResEnableHap()1279 bool HapManager::IsThemeSystemResEnableHap()
1280 {
1281     ReadLock lock(this->mutex_);
1282     return this->isThemeSystemResEnable_;
1283 }
1284 
IsSystem()1285 bool HapManager::IsSystem()
1286 {
1287     return this->isSystem_;
1288 }
1289 
GetLoadedHapPaths()1290 std::unordered_map<std::string, std::vector<std::string>> HapManager::GetLoadedHapPaths()
1291 {
1292     return this->loadedHapPaths_;
1293 }
1294 
UpdateAppConfigForSysResManager(bool isAppDarkRes,bool isThemeSystemResEnable)1295 void HapManager::UpdateAppConfigForSysResManager(bool isAppDarkRes, bool isThemeSystemResEnable)
1296 {
1297     WriteLock lock(this->mutex_);
1298     if (this->isSystem_ && this->isUpdateAppConfig_) {
1299         this->isUpdateAppConfig_ = false;
1300         this->resConfig_->SetAppDarkRes(isAppDarkRes);
1301         this->isThemeSystemResEnable_ = isThemeSystemResEnable;
1302     }
1303 }
1304 } // namespace Resource
1305 } // namespace Global
1306 } // namespace OHOS
1307