• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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__)
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<HapResource::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<HapResource::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<HapResource::ValueUnderQualifierDir> HapManager::FindQualifierValueById(uint32_t id,
203     bool isGetOverrideResource, uint32_t density)
204 {
205     ReadLock lock(this->mutex_);
206     std::vector<std::shared_ptr<HapResource::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<HapResource::ValueUnderQualifierDir> & result,const std::vector<std::shared_ptr<HapResource::ValueUnderQualifierDir>> & paths,uint32_t density,std::shared_ptr<ResConfigImpl> currentResConfig)259 void HapManager::MatchBestResource(std::shared_ptr<ResConfigImpl> &bestResConfig,
260     std::shared_ptr<HapResource::ValueUnderQualifierDir> &result,
261     const std::vector<std::shared_ptr<HapResource::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<HapResource::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<HapResource::IdValues>> & candidates,uint32_t density,bool isGetOverrideResource)284 const std::shared_ptr<HapResource::ValueUnderQualifierDir> HapManager::GetBestMatchResource(
285     const std::vector<std::shared_ptr<HapResource::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<HapResource::ValueUnderQualifierDir> result = nullptr;
290     std::shared_ptr<HapResource::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]->IsOverlay();
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, %s", indexPath.c_str());
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->UpdateResConfig(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->UpdateResConfig(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     return this->AddResourcePath(path, selectedTypes, forceReload);
427 }
428 
AddPatchResource(const char * path,const char * patchPath)429 bool HapManager::AddPatchResource(const char *path, const char *patchPath)
430 {
431     WriteLock lock(this->mutex_);
432     return this->AddPatchResourcePath(path, patchPath);
433 }
434 
AddResource(const std::string & path,const std::vector<std::string> & overlayPaths)435 bool HapManager::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
436 {
437     WriteLock lock(this->mutex_);
438     std::vector<std::string> targetOverlay = loadedHapPaths_[path];
439     if (!targetOverlay.empty() && targetOverlay == overlayPaths) {
440         RESMGR_HILOGI(RESMGR_TAG, "the overlay for %{public}s already been loaded", path.c_str());
441         return true;
442     }
443     std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
444     std::unordered_map<std::string, std::shared_ptr<HapResource>> result = HapResource::LoadOverlays(path, overlayPaths,
445         config, isSystem_);
446     if (result.size() == 0) {
447         return false;
448     }
449     if (result.find(path) != result.end()) {
450         hapResources_.push_back(result[path]);
451         if (result[path]->HasDarkRes()) {
452             this->resConfig_->SetAppDarkRes(true);
453         }
454     }
455     for (auto iter = overlayPaths.rbegin(); iter != overlayPaths.rend(); iter++) {
456         if (result.find(*iter) != result.end()) {
457             hapResources_.push_back(result[*iter]);
458         }
459     }
460     loadedHapPaths_[path] = overlayPaths;
461     return true;
462 }
463 
GetValidAppPath()464 std::string HapManager::GetValidAppPath()
465 {
466     std::string appPath;
467     ReadLock lock(this->mutex_);
468     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
469         const std::string tempPath = (*iter)->GetIndexPath();
470         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
471             continue;
472         }
473         appPath = tempPath;
474     }
475     return appPath;
476 }
477 
AddAppOverlay(const std::string & overlayPath)478 bool HapManager::AddAppOverlay(const std::string &overlayPath)
479 {
480     RESMGR_HILOGI(RESMGR_TAG, "AddAppOverlay overlayPath = %{public}s", overlayPath.c_str());
481     char outPath[PATH_MAX + 1] = {0};
482     Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
483     if (outPath[0] == '\0') {
484         RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath, %{public}s", overlayPath.c_str());
485         return false;
486     }
487     std::vector<std::string> overlayPaths;
488     overlayPaths.emplace_back(outPath);
489     std::string appPath = GetValidAppPath();
490     return AddResource(appPath, overlayPaths);
491 }
492 
RemoveAppOverlay(const std::string & overlayPath)493 bool HapManager::RemoveAppOverlay(const std::string &overlayPath)
494 {
495     RESMGR_HILOGI(RESMGR_TAG, "RemoveAppOverlay overlayPath = %{public}s", overlayPath.c_str());
496     char outPath[PATH_MAX + 1] = {0};
497     Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
498     if (outPath[0] == '\0') {
499         RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath, %{public}s", overlayPath.c_str());
500         return false;
501     }
502     std::vector<std::string> overlayPaths;
503     overlayPaths.emplace_back(outPath);
504     std::string appPath = GetValidAppPath();
505     return RemoveResource(appPath, overlayPaths);
506 }
507 
~HapManager()508 HapManager::~HapManager()
509 {
510     WriteLock lock(this->mutex_);
511     hapResources_.clear();
512     loadedHapPaths_.clear();
513 #ifdef SUPPORT_GRAPHICS
514     auto iter = plurRulesCache_.begin();
515     for (; iter != plurRulesCache_.end(); iter++) {
516         RESMGR_HILOGD(RESMGR_TAG, "delete plurRulesMap_ %s", iter->first.c_str());
517         if (iter->second != nullptr) {
518             auto ptr = iter->second;
519             delete (ptr);
520             iter->second = nullptr;
521         }
522     }
523 #endif
524 }
525 
GetResourceList(uint32_t ident) const526 std::vector<std::shared_ptr<HapResource::IdValues>> HapManager::GetResourceList(uint32_t ident) const
527 {
528     std::vector<std::shared_ptr<HapResource::IdValues>> result;
529     // one id only exit in one hap
530     for (size_t i = 0; i < hapResources_.size(); ++i) {
531         std::shared_ptr<HapResource> pResource = hapResources_[i];
532         const std::shared_ptr<HapResource::IdValues>out = pResource->GetIdValues(ident);
533         if (out != nullptr) {
534             result.emplace_back(out);
535         }
536     }
537     return result;
538 }
539 
GetResourceListByName(const char * name,const ResType resType) const540 std::vector<std::shared_ptr<HapResource::IdValues>> HapManager::GetResourceListByName(const char *name,
541     const ResType resType) const
542 {
543     std::vector<std::shared_ptr<HapResource::IdValues>> result;
544     // all match will return
545     if (name == nullptr) {
546         return result;
547     }
548     std::string key(name);
549     for (size_t i = 0; i < hapResources_.size(); ++i) {
550         std::shared_ptr<HapResource> pResource = hapResources_[i];
551         const std::shared_ptr<HapResource::IdValues> out = pResource->GetIdValuesByName(key, resType);
552         if (out != nullptr) {
553             result.emplace_back(out);
554         }
555     }
556     return result;
557 }
558 
AddResourcePath(const char * path,const uint32_t & selectedTypes,bool forceReload)559 bool HapManager::AddResourcePath(const char *path, const uint32_t &selectedTypes, bool forceReload)
560 {
561     std::string sPath(path);
562 #if defined(__ARKUI_CROSS__)
563     if (forceReload) {
564         HapResourceManager::GetInstance()->RemoveHapResource(sPath);
565         RemoveHapResource(sPath);
566     }
567 #endif
568     auto it = loadedHapPaths_.find(sPath);
569     if (it != loadedHapPaths_.end()) {
570         return false;
571     }
572     std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
573     std::shared_ptr<HapResource> pResource = HapResource::Load(path, config, isSystem_, false, selectedTypes);
574     if (pResource == nullptr) {
575         return false;
576     }
577     this->loadedHapPaths_[sPath] = std::vector<std::string>();
578     this->hapResources_.push_back(pResource);
579     if (pResource->HasDarkRes()) {
580         this->resConfig_->SetAppDarkRes(true);
581     }
582     return true;
583 }
584 
585 #if defined(__ARKUI_CROSS__)
RemoveHapResource(const std::string & path)586 void HapManager::RemoveHapResource(const std::string &path)
587 {
588     for (auto iter = hapResources_.begin(); iter != hapResources_.end();) {
589         if ((*iter)->GetIndexPath() == path) {
590             iter = hapResources_.erase(iter);
591             break;
592         } else {
593             ++iter;
594         }
595     }
596 
597     auto it = loadedHapPaths_.find(path);
598     if (it != loadedHapPaths_.end()) {
599         loadedHapPaths_.erase(it);
600     }
601 }
602 #endif
603 
AddPatchResourcePath(const char * path,const char * patchPath)604 bool HapManager::AddPatchResourcePath(const char *path, const char *patchPath)
605 {
606     std::string sPath(path);
607     auto it = loadedHapPaths_.find(sPath);
608     if (it == loadedHapPaths_.end()) {
609         RESMGR_HILOGW(RESMGR_TAG, "AddPatchResourcePath hapPath not load, hapPath = %{public}s", sPath.c_str());
610         return false;
611     }
612     std::string sPatchPath(patchPath);
613     return HapResourceManager::GetInstance()->PutPatchResource(sPath, sPatchPath);
614 }
615 
ReloadAll()616 RState HapManager::ReloadAll()
617 {
618     WriteLock lock(this->mutex_);
619     if (hapResources_.size() == 0) {
620         return SUCCESS;
621     }
622     std::vector<std::shared_ptr<HapResource>> newResources;
623     for (auto iter = loadedHapPaths_.begin(); iter != loadedHapPaths_.end(); iter++) {
624         std::vector<std::string> &overlayPaths = iter->second;
625         if (overlayPaths.size() == 0) {
626             const auto pResource = HapResource::Load(iter->first.c_str(), resConfig_);
627             if (pResource == nullptr) {
628                 newResources.clear();
629                 return HAP_INIT_FAILED;
630             }
631             newResources.push_back(pResource);
632             continue;
633         }
634         std::unordered_map<std::string, std::shared_ptr<HapResource>> result = HapResource::LoadOverlays(
635             iter->first.c_str(), overlayPaths, resConfig_);
636         if (result.size() == 0) {
637             continue;
638         }
639         for (auto iter = result.begin(); iter != result.end(); iter++) {
640             newResources.push_back(iter->second);
641         }
642     }
643     hapResources_.clear();
644     hapResources_ = newResources;
645     return SUCCESS;
646 }
647 
GetResourcePaths()648 std::vector<std::string> HapManager::GetResourcePaths()
649 {
650     std::vector<std::string> result;
651     ReadLock lock(this->mutex_);
652     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
653         std::string indexPath = (*iter)->GetIndexPath();
654         auto index = indexPath.rfind('/');
655         if (index == std::string::npos) {
656             RESMGR_HILOGE(RESMGR_TAG, "index path format error, %s", indexPath.c_str());
657             continue;
658         }
659 
660         result.emplace_back(indexPath.substr(0, index) + "/resources/");
661     }
662 
663     return result;
664 }
665 
GetImageType(const std::string fileName)666 std::string GetImageType(const std::string fileName)
667 {
668     auto pos = fileName.find_last_of('.');
669     std::string imgType;
670     if (pos != std::string::npos) {
671         imgType = fileName.substr(pos + 1);
672     }
673     return imgType;
674 }
675 
676 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> & extractor,const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,const ResType resType)677 std::string GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> &extractor,
678     const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, const ResType resType)
679 {
680     std::string filePath;
681     if (qd == nullptr) {
682         RESMGR_HILOGE(RESMGR_TAG, "GetFilePathFromHap qd is null");
683         return filePath;
684     }
685     const std::shared_ptr<IdItem> idItem = qd->GetIdItem();
686     if (idItem == nullptr || idItem->resType_ != resType) {
687         std::string hapPath = qd->GetIndexPath();
688         RESMGR_HILOGE(RESMGR_TAG, "actual resType = %{public}d, expect resType = %{public}d, hapPath = %{public}s",
689             idItem == nullptr ? -1 : idItem->resType_, resType, hapPath.c_str());
690         return filePath;
691     }
692     if (extractor->IsStageModel()) {
693         std::string tempFilePath(idItem->value_);
694         auto index = tempFilePath.find('/');
695         if (index == std::string::npos) {
696             RESMGR_HILOGE(RESMGR_TAG, "resource path format error, %s", tempFilePath.c_str());
697             return filePath;
698         }
699         filePath = idItem->value_.substr(index + 1);
700     } else {
701         // FA mode
702         std::string tempFilePath("assets/");
703         tempFilePath.append(idItem->value_);
704         filePath = tempFilePath;
705     }
706     return filePath;
707 }
708 
GetAbilityExtractor(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd)709 std::shared_ptr<AbilityBase::Extractor> GetAbilityExtractor(
710     const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd)
711 {
712     std::string hapPath = qd->GetIndexPath();
713     bool isNewExtractor = false;
714     auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
715     return extractor;
716 }
717 #endif
718 
GetProfileData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)719 RState HapManager::GetProfileData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
720     std::unique_ptr<uint8_t[]> &outValue)
721 {
722 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
723     auto extractor = GetAbilityExtractor(qd);
724     if (extractor == nullptr) {
725         RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
726         return NOT_FOUND;
727     }
728     std::string filePath = GetFilePathFromHap(extractor, qd, ResType::PROF);
729     if (filePath.empty()) {
730         RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetProfileData");
731         return NOT_FOUND;
732     }
733     bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
734     if (!ret) {
735         RESMGR_HILOGE(RESMGR_TAG, "failed to get config data from ability");
736         return NOT_FOUND;
737     }
738 #endif
739     return SUCCESS;
740 }
741 
GetMediaData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)742 RState HapManager::GetMediaData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
743     std::unique_ptr<uint8_t[]> &outValue)
744 {
745     std::string filePath = qd->GetIndexPath();
746     RState state;
747     if (Utils::ContainsTail(filePath, Utils::tailSet)) {
748         state = HapManager::GetMediaDataFromHap(qd, len, outValue);
749     } else {
750         state = HapManager::GetMediaDataFromIndex(qd, len, outValue);
751     }
752     return state;
753 }
754 
GetMediaDataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)755 RState HapManager::GetMediaDataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
756     std::unique_ptr<uint8_t[]> &outValue)
757 {
758 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
759     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
760     auto extractor = GetAbilityExtractor(qd);
761     if (extractor == nullptr) {
762         RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
763         return NOT_FOUND;
764     }
765     std::string filePath = GetFilePathFromHap(extractor, qd, ResType::MEDIA);
766     if (filePath.empty()) {
767         RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetMediaDataFromHap");
768         return NOT_FOUND;
769     }
770     bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
771     if (!ret) {
772         RESMGR_HILOGE(RESMGR_TAG, "failed to get media data from ability");
773         return NOT_FOUND;
774     }
775 #endif
776     return SUCCESS;
777 }
778 
GetMediaDataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)779 RState HapManager::GetMediaDataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
780     std::unique_ptr<uint8_t[]> &outValue)
781 {
782     std::string filePath;
783     RState state = HapManager::GetFilePath(qd, ResType::MEDIA, filePath);
784     if (state != SUCCESS) {
785         return NOT_FOUND;
786     }
787     outValue = Utils::LoadResourceFile(filePath, len);
788     return SUCCESS;
789 }
790 
GetMediaBase64Data(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,std::string & outValue)791 RState HapManager::GetMediaBase64Data(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,
792     std::string &outValue)
793 {
794     std::string filePath = qd->GetIndexPath();
795     RState state;
796     if (Utils::ContainsTail(filePath, Utils::tailSet)) {
797         state = HapManager::GetMediaBase64DataFromHap(qd, outValue);
798     } else {
799         state = HapManager::GetMediaBase64DataFromIndex(qd, outValue);
800     }
801     return state;
802 }
803 
GetMediaBase64DataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,std::string & outValue)804 RState HapManager::GetMediaBase64DataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,
805     std::string &outValue)
806 {
807 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
808     auto extractor = GetAbilityExtractor(qd);
809     if (extractor == nullptr) {
810         RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
811         return NOT_FOUND;
812     }
813     std::string filePath = GetFilePathFromHap(extractor, qd, ResType::MEDIA);
814     std::unique_ptr<uint8_t[]> buffer;
815     size_t tmpLen;
816     bool ret = extractor->ExtractToBufByName(filePath, buffer, tmpLen);
817     if (!ret) {
818         RESMGR_HILOGE(RESMGR_TAG, "failed to get mediabase64 data from ability");
819         return NOT_FOUND;
820     }
821     std::string imgType = GetImageType(filePath);
822     Utils::EncodeBase64(buffer, tmpLen, imgType, outValue);
823 #endif
824     return SUCCESS;
825 }
826 
GetMediaBase64DataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,std::string & outValue)827 RState HapManager::GetMediaBase64DataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,
828     std::string &outValue)
829 {
830     std::string filePath;
831     RState state = HapManager::GetFilePath(qd, ResType::MEDIA, filePath);
832     if (state != SUCCESS) {
833         return NOT_FOUND;
834     }
835     return Utils::GetMediaBase64Data(filePath, outValue);
836 }
837 
GetValidHapPath(std::string & hapPath)838 int32_t HapManager::GetValidHapPath(std::string &hapPath)
839 {
840     ReadLock lock(this->mutex_);
841     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
842         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
843             continue;
844         }
845         const std::string tempPath = (*iter)->GetIndexPath();
846         if (Utils::ContainsTail(tempPath, Utils::tailSet)) {
847             hapPath = tempPath;
848             return OK;
849         }
850     }
851     return NOT_FOUND;
852 }
853 
GetValidIndexPath(std::string & indexPath)854 int32_t HapManager::GetValidIndexPath(std::string &indexPath)
855 {
856     ReadLock lock(this->mutex_);
857     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
858         const std::string tempPath = (*iter)->GetIndexPath();
859         if (Utils::endWithTail(tempPath, "/systemres/resources.index")) {
860             continue;
861         }
862         indexPath = tempPath;
863         return OK;
864     }
865     return NOT_FOUND;
866 }
867 
FindRawFileFromHap(const std::string & rawFileName,size_t & len,std::unique_ptr<uint8_t[]> & outValue)868 RState HapManager::FindRawFileFromHap(const std::string &rawFileName, size_t &len,
869     std::unique_ptr<uint8_t[]> &outValue)
870 {
871     ReadLock lock(this->mutex_);
872     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
873         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
874             continue;
875         }
876         std::string tempPath = (*iter)->GetIndexPath();
877         std::string tempPatchPath;
878         if ((*iter)->IsPatch()) {
879             tempPatchPath = (*iter)->GetPatchPath();
880         }
881         if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
882             RState state = HapParser::ReadRawFileFromHap(tempPath, tempPatchPath, rawFileName, len, outValue);
883             if (state != SUCCESS) {
884                 continue;
885             }
886         } else { // if file path is uncompressed
887             std::string filePath;
888             HapManager::FindRawFile(rawFileName, filePath);
889             outValue = Utils::LoadResourceFile(filePath, len);
890             if (outValue == nullptr) {
891                 continue;
892             }
893         }
894         return SUCCESS;
895     }
896     return ERROR_CODE_RES_PATH_INVALID;
897 }
898 
FindRawFileDescriptorFromHap(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)899 RState HapManager::FindRawFileDescriptorFromHap(const std::string &rawFileName,
900     ResourceManager::RawFileDescriptor &descriptor)
901 {
902     std::lock_guard<std::mutex> lock(g_rawFileLock);
903     auto it = rawFileDescriptor_.find(rawFileName);
904     if (it != rawFileDescriptor_.end()) {
905         descriptor.fd = rawFileDescriptor_[rawFileName].fd;
906         descriptor.length = rawFileDescriptor_[rawFileName].length;
907         descriptor.offset = rawFileDescriptor_[rawFileName].offset;
908         return SUCCESS;
909     }
910     RState state = GetRawFd(rawFileName, descriptor);
911     if (state == SUCCESS) {
912         rawFileDescriptor_[rawFileName] = descriptor;
913     }
914     return state;
915 }
916 
GetRawFd(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)917 RState HapManager::GetRawFd(const std::string &rawFileName, ResourceManager::RawFileDescriptor &descriptor)
918 {
919     RState state;
920     ReadLock lock(this->mutex_);
921     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
922         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
923             continue;
924         }
925         std::string tempPath = (*iter)->GetIndexPath();
926         std::string tempPatchPath;
927         if ((*iter)->IsPatch()) {
928             tempPatchPath = (*iter)->GetPatchPath();
929         }
930         if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
931             state = HapParser::ReadRawFileDescriptor(tempPath.c_str(), tempPatchPath.c_str(), rawFileName, descriptor);
932         } else { // if file path is uncompressed
933             state = HapManager::FindRawFileDescriptor(rawFileName, descriptor);
934         }
935         if (state != SUCCESS) {
936             continue;
937         }
938         return SUCCESS;
939     }
940     return ERROR_CODE_RES_PATH_INVALID;
941 }
942 
GetRawFileList(const std::string & rawDirPath,std::vector<std::string> & fileList)943 RState HapManager::GetRawFileList(const std::string &rawDirPath, std::vector<std::string> &fileList)
944 {
945     std::string hapOrIndexPath;
946     if (HapManager::GetValidHapPath(hapOrIndexPath) == OK) {
947         std::string temPatchPath;
948         {
949             ReadLock lock(this->mutex_);
950             for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
951                 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
952                     continue;
953                 }
954                 if ((*iter)->GetIndexPath() == hapOrIndexPath && (*iter)->IsPatch()) {
955                     temPatchPath = (*iter)->GetPatchPath();
956                 }
957             }
958         }
959         std::set<std::string> fileSet;
960         RState hapState = HapParser::GetRawFileList(hapOrIndexPath, rawDirPath, fileSet);
961         RState hqfState = NOT_FOUND;
962         if (!temPatchPath.empty()) {
963             hqfState = HapParser::GetRawFileList(temPatchPath, rawDirPath, fileSet);
964         }
965         for (auto it = fileSet.begin(); it != fileSet.end(); it++) {
966             fileList.emplace_back(*it);
967         }
968         return (hapState != SUCCESS && hqfState != SUCCESS) ? ERROR_CODE_RES_PATH_INVALID : SUCCESS;
969     }
970     if (HapManager::GetValidIndexPath(hapOrIndexPath) == OK) {
971         return  HapParser::GetRawFileListUnCompressed(hapOrIndexPath, rawDirPath, fileList);
972     }
973     return ERROR_CODE_RES_PATH_INVALID;
974 }
975 
IsLoadHap(std::string & hapPath)976 bool HapManager::IsLoadHap(std::string &hapPath)
977 {
978     return HapManager::GetValidHapPath(hapPath) == OK ? true : false;
979 }
980 
GetFilePath(const std::shared_ptr<HapResource::ValueUnderQualifierDir> vuqd,const ResType resType,std::string & outValue)981 RState HapManager::GetFilePath(const std::shared_ptr<HapResource::ValueUnderQualifierDir> vuqd, const ResType resType,
982     std::string &outValue)
983 {
984     // not found or type invalid
985     if (vuqd == nullptr) {
986         return NOT_FOUND;
987     }
988     const std::shared_ptr<IdItem> idItem = vuqd->GetIdItem();
989     if (idItem == nullptr || idItem->resType_ != resType) {
990         return NOT_FOUND;
991     }
992     outValue = vuqd->GetResourcePath();
993 #if defined(__ARKUI_CROSS__)
994     auto index = idItem->value_.find('/');
995     if (index == std::string::npos) {
996         RESMGR_HILOGE(RESMGR_TAG, "resource path format error, %s", idItem->value_.c_str());
997         return NOT_FOUND;
998     }
999     auto nameWithoutModule = idItem->value_.substr(index + 1);
1000     outValue.append(nameWithoutModule);
1001 #elif defined(__IDE_PREVIEW__)
1002     if (Utils::IsFileExist(idItem->value_)) {
1003         outValue = idItem->value_;
1004         return SUCCESS;
1005     }
1006     auto index = idItem->value_.find('/');
1007     if (index == std::string::npos) {
1008         RESMGR_HILOGE(RESMGR_TAG, "resource path format error, %s", idItem->value_.c_str());
1009         return NOT_FOUND;
1010     }
1011     auto nameWithoutModule = idItem->value_.substr(index + 1);
1012     outValue.append(nameWithoutModule);
1013 #else
1014     outValue.append(idItem->value_);
1015 #endif
1016     return SUCCESS;
1017 }
1018 
FindRawFileDescriptor(const std::string & name,ResourceManager::RawFileDescriptor & descriptor)1019 RState HapManager::FindRawFileDescriptor(const std::string &name, ResourceManager::RawFileDescriptor &descriptor)
1020 {
1021     std::string paths = "";
1022     RState rState = HapManager::FindRawFile(name, paths);
1023     if (rState != SUCCESS) {
1024         return rState;
1025     }
1026     char outPath[PATH_MAX + 1] = {0};
1027     Utils::CanonicalizePath(paths.c_str(), outPath, PATH_MAX);
1028     int fd = open(outPath, O_RDONLY);
1029     if (fd > 0) {
1030         long length = lseek(fd, 0, SEEK_END);
1031         if (length == -1) {
1032             close(fd);
1033             return ERROR_CODE_RES_PATH_INVALID;
1034         }
1035         long begin = lseek(fd, 0, SEEK_SET);
1036         if (begin == -1) {
1037             close(fd);
1038             return ERROR_CODE_RES_PATH_INVALID;
1039         }
1040         descriptor.fd = fd;
1041         descriptor.length = length;
1042         descriptor.offset = 0;
1043         return SUCCESS;
1044     }
1045     return ERROR_CODE_RES_PATH_INVALID;
1046 }
1047 
CloseRawFileDescriptor(const std::string & name)1048 RState HapManager::CloseRawFileDescriptor(const std::string &name)
1049 {
1050     std::lock_guard<std::mutex> lock(g_rawFileLock);
1051     auto it = rawFileDescriptor_.find(name);
1052     if (it == rawFileDescriptor_.end()) {
1053         return ERROR_CODE_RES_PATH_INVALID;
1054     }
1055 
1056     int fd = rawFileDescriptor_[name].fd;
1057     if (fd <= 0) {
1058         return ERROR_CODE_RES_PATH_INVALID;
1059     }
1060 
1061 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
1062     if (fdsan_get_owner_tag(fd) != 0) {
1063         rawFileDescriptor_.erase(name);
1064         return SUCCESS;
1065     }
1066 #endif
1067 
1068     if (close(fd) == -1) {
1069         return ERROR_CODE_RES_PATH_INVALID;
1070     }
1071 
1072     rawFileDescriptor_.erase(name);
1073     return SUCCESS;
1074 }
1075 
RemoveResource(const std::string & path,const std::vector<std::string> & overlayPaths)1076 bool HapManager::RemoveResource(const std::string &path, const std::vector<std::string> &overlayPaths)
1077 {
1078     WriteLock lock(this->mutex_);
1079     RESMGR_HILOGI(RESMGR_TAG, "remove overlay for path, %{public}s", path.c_str());
1080     if (loadedHapPaths_.find(path) == loadedHapPaths_.end()) {
1081         return false;
1082     }
1083     std::vector<std::string> targetOverlay = loadedHapPaths_[path];
1084     if (targetOverlay.empty()) {
1085         RESMGR_HILOGE(RESMGR_TAG, "the %{public}s have not overlay", path.c_str());
1086         return false;
1087     }
1088     char outPath[PATH_MAX] = {0};
1089     for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
1090         Utils::CanonicalizePath((*iter).c_str(), outPath, PATH_MAX);
1091         if (outPath[0] == '\0') {
1092             RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath, %{public}s", (*iter).c_str());
1093             continue;
1094         }
1095         if (std::find(targetOverlay.begin(), targetOverlay.end(), outPath) != targetOverlay.end()) {
1096             targetOverlay.erase(std::remove(targetOverlay.begin(), targetOverlay.end(), outPath),
1097                 targetOverlay.end());
1098         }
1099         for (auto resIter = hapResources_.begin(); resIter != hapResources_.end();) {
1100             if ((*resIter) == nullptr) {
1101                 RESMGR_HILOGE(RESMGR_TAG, "hapResource is nullptr");
1102                 return false;
1103             }
1104             std::string hapPath = (*resIter)->GetIndexPath();
1105             if (hapPath == outPath) {
1106                 resIter = hapResources_.erase(resIter);
1107             } else {
1108                 resIter++;
1109             }
1110         }
1111     }
1112     loadedHapPaths_[path] = targetOverlay;
1113     return true;
1114 }
1115 
GetHapResource()1116 std::vector<std::shared_ptr<HapResource>> HapManager::GetHapResource()
1117 {
1118     return hapResources_;
1119 }
1120 
AddSystemResource(const std::shared_ptr<HapManager> & systemHapManager)1121 void HapManager::AddSystemResource(const std::shared_ptr<HapManager> &systemHapManager)
1122 {
1123     if (systemHapManager == nullptr) {
1124         RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, systemHapManager is nullptr");
1125         return;
1126     }
1127     if (!systemHapManager->isSystem_) {
1128         RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, the added hapManager is not system");
1129         return;
1130     }
1131     WriteLock lock(this->mutex_);
1132     // add system resource to app resource vector
1133     const std::vector<std::shared_ptr<HapResource>> &systemResources = systemHapManager->hapResources_;
1134     for (size_t i = 0; i < systemResources.size(); i++) {
1135         this->hapResources_.push_back(systemResources[i]);
1136     }
1137 
1138     // add system loaded path to app loaded path map.
1139     const std::unordered_map<std::string, std::vector<std::string>> &loadedSystemPaths =
1140         systemHapManager->loadedHapPaths_;
1141     for (auto iter = loadedSystemPaths.begin(); iter != loadedSystemPaths.end(); iter++) {
1142         const std::vector<std::string> &overlayPaths = iter->second;
1143         if (this->loadedHapPaths_.find(iter->first) == this->loadedHapPaths_.end()) {
1144             this->loadedHapPaths_[iter->first] = overlayPaths;
1145         }
1146     }
1147 }
1148 
GetResourceLimitKeys()1149 uint32_t HapManager::GetResourceLimitKeys()
1150 {
1151     ReadLock lock(this->mutex_);
1152     uint32_t limitKeysValue = 0;
1153     for (size_t i = 0; i < hapResources_.size(); i++) {
1154         limitKeysValue |= hapResources_[i]->GetResourceLimitKeys();
1155     }
1156     RESMGR_HILOGD(RESMGR_TAG, "hap manager limit key is %{public}u", limitKeysValue);
1157     return limitKeysValue;
1158 }
1159 
1160 std::unordered_map<std::string, ResType> ResTypeMap {
1161     {"integer", INTEGER},
1162     {"string", STRING},
1163     {"strarray", STRINGARRAY},
1164     {"intarray", INTARRAY},
1165     {"boolean", BOOLEAN},
1166     {"color", COLOR},
1167     {"theme", THEME},
1168     {"plural", PLURALS},
1169     {"float", FLOAT},
1170     {"media", MEDIA},
1171     {"profile", PROF},
1172     {"pattern", PATTERN},
1173 };
1174 
IsPrefix(std::string_view prefix,std::string_view full)1175 bool IsPrefix(std::string_view prefix, std::string_view full)
1176 {
1177     return prefix == full.substr(0, prefix.size());
1178 }
1179 
GetRealResId(const std::string & resType,const std::vector<std::unordered_map<ResType,uint32_t>> & candidates)1180 uint32_t GetRealResId(const std::string &resType,
1181     const std::vector<std::unordered_map<ResType, uint32_t>> &candidates)
1182 {
1183     for (auto candidate : candidates) {
1184         for (auto data : candidate) {
1185             if (ResTypeMap.find(resType) != ResTypeMap.end() && ResTypeMap[resType] == data.first) {
1186                 return data.second;
1187             }
1188         }
1189     }
1190     return 0;
1191 }
1192 
GetResTypeAndResName(const std::string & resTypeName)1193 std::tuple<std::string, std::string> GetResTypeAndResName(const std::string &resTypeName)
1194 {
1195     std::tuple<std::string, std::string> typeNameTuple;
1196     auto pos1 = resTypeName.find('.');
1197     auto pos2 = resTypeName.rfind('.');
1198     if (pos1 == std::string::npos || pos2 == std::string::npos) {
1199         return std::make_tuple("", "");
1200     }
1201     if (pos2 < pos1 + 1) {
1202         return std::make_tuple("", "");
1203     }
1204     const std::string resType = resTypeName.substr(pos1 + 1, pos2 - pos1 - 1);
1205     if (ResTypeMap.find(resType) == ResTypeMap.end()) {
1206         return std::make_tuple("", "");
1207     }
1208     const std::string resName = resTypeName.substr(pos2 + 1);
1209     if (resName.empty()) {
1210         return std::make_tuple("", "");
1211     }
1212     typeNameTuple = std::make_tuple(resType, resName);
1213     return typeNameTuple;
1214 }
1215 
GetResId(const std::string & resTypeName,uint32_t & resId)1216 RState HapManager::GetResId(const std::string &resTypeName, uint32_t &resId)
1217 {
1218     auto typeNameTuple = GetResTypeAndResName(resTypeName);
1219     const std::string resType =  std::get<0>(typeNameTuple);
1220     const std::string resName =  std::get<1>(typeNameTuple);
1221     if (resType.empty() || resName.empty()) {
1222         RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1223         return NOT_FOUND;
1224     }
1225     bool isSystem = IsPrefix("sys", resTypeName);
1226     bool isApp = IsPrefix("app", resTypeName);
1227     if (!isSystem && !isApp) {
1228         RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1229         return NOT_FOUND;
1230     }
1231     ReadLock lock(this->mutex_);
1232     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1233         bool isSystemResource = (*iter)->IsSystemResource();
1234         bool isOverlayResource = (*iter)->IsOverlayResource();
1235         if (isOverlayResource) {
1236             continue;
1237         }
1238         if (isSystem && !isSystemResource) {
1239             continue;
1240         }
1241         if (isApp && isSystemResource) {
1242             continue;
1243         }
1244         std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> nameTypeIdMap =
1245                 (*iter)->BuildNameTypeIdMapping();
1246         std::vector<std::unordered_map<ResType, uint32_t>> candidates;
1247         for (auto data : nameTypeIdMap) {
1248             if (data.first != resName) {
1249                 continue;
1250             }
1251             candidates.emplace_back(data.second);
1252         }
1253         resId = GetRealResId(resType, candidates);
1254         if (resId == 0) {
1255             RESMGR_HILOGE(RESMGR_TAG,
1256                 "GetResId name = %{public}s, resType = %{public}s", resName.c_str(), resType.c_str());
1257             return NOT_FOUND;
1258         }
1259     }
1260     return SUCCESS;
1261 }
1262 
GetLocales(std::vector<std::string> & outValue,bool includeSystem)1263 void HapManager::GetLocales(std::vector<std::string> &outValue, bool includeSystem)
1264 {
1265     if (isSystem_) {
1266         includeSystem = true;
1267     }
1268     std::set<std::string> result;
1269     ReadLock lock(this->mutex_);
1270     for (size_t i = 0; i < hapResources_.size(); i++) {
1271         hapResources_[i]->GetLocales(result, includeSystem);
1272     }
1273     outValue.assign(result.begin(), result.end());
1274 }
1275 
IsRawDirFromHap(const std::string & pathName,bool & outValue)1276 RState HapManager::IsRawDirFromHap(const std::string &pathName, bool &outValue)
1277 {
1278     ReadLock lock(this->mutex_);
1279     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1280         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
1281             continue;
1282         }
1283         const std::string tempPath = (*iter)->GetIndexPath();
1284         if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
1285             RState state = HapParser::IsRawDirFromHap(tempPath.c_str(), pathName, outValue);
1286             if (state != SUCCESS) {
1287                 continue;
1288             }
1289         } else { // if file path is uncompressed
1290 #if !defined(__ARKUI_CROSS__)
1291             RState state = HapParser::IsRawDirUnCompressed(pathName, outValue);
1292             if (state != SUCCESS) {
1293                 continue;
1294             }
1295 #else
1296             const std::string finalPath = (*iter)->GetResourcePath() + RAW_FILE_PATH + pathName;
1297             RState state = HapParser::IsRawDirUnCompressed(finalPath, outValue);
1298             if (state != SUCCESS) {
1299                 continue;
1300             }
1301 #endif
1302         }
1303         return SUCCESS;
1304     }
1305     return ERROR_CODE_RES_PATH_INVALID;
1306 }
1307 
IsThemeSystemResEnableHap()1308 bool HapManager::IsThemeSystemResEnableHap()
1309 {
1310     ReadLock lock(this->mutex_);
1311     for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1312         if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
1313             continue;
1314         }
1315         if ((*iter)->IsThemeSystemResEnable()) {
1316             return true;
1317         }
1318     }
1319     return false;
1320 }
1321 
IsSystem()1322 bool HapManager::IsSystem()
1323 {
1324     return this->isSystem_;
1325 }
1326 
GetLoadedHapPaths()1327 std::unordered_map<std::string, std::vector<std::string>> HapManager::GetLoadedHapPaths()
1328 {
1329     return this->loadedHapPaths_;
1330 }
1331 } // namespace Resource
1332 } // namespace Global
1333 } // namespace OHOS
1334