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