1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hap_resource.h"
17 
18 #include <algorithm>
19 #include <climits>
20 #include <cstdlib>
21 #include <fstream>
22 #include "utils/utils.h"
23 #include <set>
24 #ifdef __WINNT__
25 #include <shlwapi.h>
26 #include <windows.h>
27 #endif
28 
29 #ifdef __LINUX__
30 #include <cstring>
31 #endif
32 
33 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
34 #include "hitrace_meter.h"
35 #include "file_mapper.h"
36 #include "extractor.h"
37 #endif
38 #include "hap_parser.h"
39 #include "hilog_wrapper.h"
40 #include "utils/errors.h"
41 
42 namespace OHOS {
43 namespace Global {
44 namespace Resource {
ValueUnderQualifierDir(const std::shared_ptr<ResKey> & resKey,const std::shared_ptr<IdItem> & idItem,const std::pair<std::string,std::string> & resPath,bool isOverlay,bool systemResource)45 HapResource::ValueUnderQualifierDir::ValueUnderQualifierDir(const std::shared_ptr<ResKey> &resKey,
46     const std::shared_ptr<IdItem> &idItem, const std::pair<std::string, std::string> &resPath, bool isOverlay,
47     bool systemResource)
48 {
49     keyParams_ = resKey->keyParams_;
50     folder_ = HapParser::ToFolderPath(keyParams_);
51     idItem_ = idItem;
52     isOverlay_ = isOverlay;
53     isSystemResource_ = systemResource;
54     resConfig_ = resKey->resConfig_;
55     indexPath_ = resPath.first;
56     resourcePath_ = resPath.second;
57 }
58 
~ValueUnderQualifierDir()59 HapResource::ValueUnderQualifierDir::~ValueUnderQualifierDir()
60 {}
61 
62 // IdValues
~IdValues()63 HapResource::IdValues::~IdValues()
64 {}
65 
66 // HapResource
HapResource(const std::string path,time_t lastModTime,std::shared_ptr<ResDesc> resDes,bool isSystem,bool isOverlay)67 HapResource::HapResource(const std::string path, time_t lastModTime, std::shared_ptr<ResDesc> resDes,
68     bool isSystem, bool isOverlay) : indexPath_(path), lastModTime_(lastModTime), resDesc_(resDes),
69     isSystem_(isSystem), isOverlay_(isOverlay), isThemeSystemResEnable_(false)
70 {}
71 
~HapResource()72 HapResource::~HapResource()
73 {
74     lastModTime_ = 0;
75 }
76 
Load(const char * path,std::shared_ptr<ResConfigImpl> & defaultConfig,bool isSystem,bool isOverlay,const uint32_t & selectedTypes)77 const std::shared_ptr<HapResource> HapResource::Load(const char *path,
78     std::shared_ptr<ResConfigImpl> &defaultConfig, bool isSystem, bool isOverlay, const uint32_t &selectedTypes)
79 {
80     if (Utils::ContainsTail(path, Utils::tailSet)) {
81         return LoadFromHap(path, defaultConfig, isSystem, isOverlay, selectedTypes);
82     } else {
83         return LoadFromIndex(path, defaultConfig, isSystem, isOverlay, selectedTypes);
84     }
85 }
86 
LoadFromIndex(const char * path,std::shared_ptr<ResConfigImpl> & defaultConfig,bool isSystem,bool isOverlay,const uint32_t & selectedTypes)87 const std::shared_ptr<HapResource> HapResource::LoadFromIndex(const char *path,
88     std::shared_ptr<ResConfigImpl> &defaultConfig, bool isSystem, bool isOverlay, const uint32_t &selectedTypes)
89 {
90     char outPath[PATH_MAX + 1] = {0};
91     Utils::CanonicalizePath(path, outPath, PATH_MAX);
92     std::ifstream inFile(outPath, std::ios::binary | std::ios::in);
93     if (!inFile.good()) {
94         return nullptr;
95     }
96     inFile.seekg(0, std::ios::end);
97     int bufLen = inFile.tellg();
98     if (bufLen <= 0) {
99         RESMGR_HILOGE(RESMGR_TAG, "file size is zero");
100         inFile.close();
101         return nullptr;
102     }
103     void *buf = malloc(bufLen);
104     if (buf == nullptr) {
105         RESMGR_HILOGE(RESMGR_TAG, "Error allocating memory");
106         inFile.close();
107         return nullptr;
108     }
109     inFile.seekg(0, std::ios::beg);
110     inFile.read(static_cast<char *>(buf), bufLen);
111     inFile.close();
112 
113     RESMGR_HILOGD(RESMGR_TAG, "extract success, bufLen:%d", bufLen);
114 
115     std::shared_ptr<ResDesc> resDesc = std::make_shared<ResDesc>();
116     if (resDesc == nullptr) {
117         RESMGR_HILOGE(RESMGR_TAG, "new ResDesc failed when LoadFromIndex");
118         free(buf);
119         return nullptr;
120     }
121     int32_t out = HapParser::ParseResHex(static_cast<char *>(buf), bufLen, *resDesc, defaultConfig, selectedTypes);
122     if (out != OK) {
123         free(buf);
124         RESMGR_HILOGE(RESMGR_TAG, "ParseResHex failed! retcode:%d", out);
125         return nullptr;
126     }
127     free(buf);
128 
129     std::shared_ptr<HapResource> pResource = std::make_shared<HapResource>(std::string(path),
130         0, resDesc, isSystem, isOverlay);
131     if (pResource == nullptr) {
132         RESMGR_HILOGE(RESMGR_TAG, "new HapResource failed when LoadFromIndex");
133         return nullptr;
134     }
135     if (!pResource->Init(defaultConfig)) {
136         return nullptr;
137     }
138     return pResource;
139 }
140 
141 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetIndexFilePath(std::shared_ptr<AbilityBase::Extractor> & extractor)142 std::string GetIndexFilePath(std::shared_ptr<AbilityBase::Extractor> &extractor)
143 {
144     std::string mName = HapParser::ParseModuleName(extractor);
145     std::string indexFilePath = std::string("assets/");
146     indexFilePath.append(mName);
147     indexFilePath.append("/resources.index");
148     return indexFilePath;
149 }
150 #endif
151 
GetIndexData(const char * path,std::unique_ptr<uint8_t[]> & tmpBuf,size_t & len)152 bool GetIndexData(const char *path, std::unique_ptr<uint8_t[]> &tmpBuf, size_t &len)
153 {
154 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
155     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
156     bool isNewExtractor = false;
157     std::shared_ptr<AbilityBase::Extractor> extractor = AbilityBase::ExtractorUtil::GetExtractor(path, isNewExtractor);
158     if (extractor == nullptr) {
159         return false;
160     }
161     std::string indexFilePath;
162     if (extractor->IsStageModel()) {
163         indexFilePath = "resources.index";
164     } else {
165         indexFilePath = GetIndexFilePath(extractor);
166     }
167     bool ret = extractor->ExtractToBufByName(indexFilePath, tmpBuf, len);
168     if (!ret) {
169         RESMGR_HILOGE(RESMGR_TAG, "failed to get buf data indexFilePath, %{public}s", indexFilePath.c_str());
170         return false;
171     }
172 #endif
173     return true;
174 }
175 
LoadFromHap(const char * path,std::shared_ptr<ResConfigImpl> & defaultConfig,bool isSystem,bool isOverlay,const uint32_t & selectedTypes)176 const std::shared_ptr<HapResource> HapResource::LoadFromHap(const char *path,
177     std::shared_ptr<ResConfigImpl> &defaultConfig, bool isSystem, bool isOverlay, const uint32_t &selectedTypes)
178 {
179     std::unique_ptr<uint8_t[]> tmpBuf;
180     size_t tmpLen = 0;
181     bool ret = GetIndexData(path, tmpBuf, tmpLen);
182     if (!ret) {
183         RESMGR_HILOGE(RESMGR_TAG, "read Index from file failed path, %{public}s", path);
184         return nullptr;
185     }
186     std::shared_ptr<ResDesc> resDesc = std::make_shared<ResDesc>();
187     if (resDesc == nullptr) {
188         RESMGR_HILOGE(RESMGR_TAG, "new ResDesc failed when LoadFromHap");
189         return nullptr;
190     }
191     int32_t out = HapParser::ParseResHex(
192         reinterpret_cast<char *>(tmpBuf.get()), tmpLen, *resDesc, defaultConfig, selectedTypes);
193     if (out != OK) {
194         RESMGR_HILOGE(RESMGR_TAG, "ParseResHex failed! retcode:%d", out);
195         return nullptr;
196     }
197 
198     auto pResource = std::make_shared<HapResource>(path, 0, resDesc, isSystem, isOverlay);
199     if (pResource == nullptr) {
200         return nullptr;
201     }
202 
203     if (!pResource->Init(defaultConfig)) {
204         return nullptr;
205     }
206     return pResource;
207 }
208 
LoadOverlays(const std::string & path,const std::vector<std::string> & overlayPaths,std::shared_ptr<ResConfigImpl> & defaultConfig,bool isSystem)209 const std::unordered_map<std::string, std::shared_ptr<HapResource>> HapResource::LoadOverlays(const std::string &path,
210     const std::vector<std::string> &overlayPaths, std::shared_ptr<ResConfigImpl> &defaultConfig, bool isSystem)
211 {
212     std::unordered_map<std::string, std::shared_ptr<HapResource>> result;
213     do {
214         const std::shared_ptr<HapResource> targetResource = Load(path.c_str(), defaultConfig, isSystem);
215         if (targetResource == nullptr) {
216             RESMGR_HILOGE(RESMGR_TAG, "load target failed");
217             break;
218         }
219         result[path] = targetResource;
220         bool success = true;
221         std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> mapping =
222             targetResource->BuildNameTypeIdMapping();
223         for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
224             // load overlay hap, the isOverlay flag set true.
225             const std::shared_ptr<HapResource> overlayResource = Load(iter->c_str(), defaultConfig, isSystem, true);
226             if (overlayResource == nullptr) {
227                 success = false;
228                 break;
229             }
230             result[*iter] = overlayResource;
231         }
232 
233         if (!success) {
234             RESMGR_HILOGE(RESMGR_TAG, "load overlay failed");
235             break;
236         }
237 
238         for (auto iter = result.begin(); iter != result.end(); iter++) {
239             auto index = iter->first.find(path);
240             if (index == std::string::npos) {
241                 iter->second->UpdateOverlayInfo(mapping);
242             }
243         }
244         return result;
245     } while (false);
246 
247     result.clear();
248     return std::unordered_map<std::string, std::shared_ptr<HapResource>>();
249 }
250 
BuildNameTypeIdMapping() const251 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> HapResource::BuildNameTypeIdMapping() const
252 {
253     std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> result;
254     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
255         const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &limitPaths = iter->second->GetLimitPathsConst();
256         if (limitPaths.size() > 0) {
257             std::shared_ptr<ValueUnderQualifierDir> value = limitPaths[0];
258             result[value->idItem_->name_][value->idItem_->resType_] = value->idItem_->id_;
259         }
260     }
261     return result;
262 }
263 
UpdateOverlayInfo(std::unordered_map<std::string,std::unordered_map<ResType,uint32_t>> & nameTypeId)264 void HapResource::UpdateOverlayInfo(std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> &nameTypeId)
265 {
266     std::map<uint32_t, std::shared_ptr<IdValues>> newIdValuesMap;
267     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
268         const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &limitPaths = iter->second->GetLimitPathsConst();
269         if (limitPaths.size() > 0) {
270             std::shared_ptr<ValueUnderQualifierDir> value = limitPaths[0];
271             std::string name = value->idItem_->name_;
272             ResType type = value->idItem_->resType_;
273             if (nameTypeId.find(name) == nameTypeId.end()) {
274                 continue;
275             }
276             auto &typeId = nameTypeId[name];
277             if (typeId.find(type) == typeId.end()) {
278                 continue;
279             }
280             uint32_t newId = typeId[type];
281             for_each(limitPaths.begin(), limitPaths.end(), [&](auto &item) {
282                 item->idItem_->id_ = newId;
283             });
284             newIdValuesMap[newId] = iter->second;
285         }
286     }
287     idValuesMap_.swap(newIdValuesMap);
288 }
289 
Init(std::shared_ptr<ResConfigImpl> & defaultConfig)290 bool HapResource::Init(std::shared_ptr<ResConfigImpl> &defaultConfig)
291 {
292 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
293     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
294 #endif
295 #ifdef __WINNT__
296     char separator = '\\';
297 #else
298     char separator = '/';
299 #endif
300     auto index = indexPath_.rfind(separator);
301     if (index == std::string::npos) {
302         RESMGR_HILOGE(RESMGR_TAG, "index path format error, %s", indexPath_.c_str());
303         return false;
304     }
305 #if defined(__IDE_PREVIEW__) || defined(__ARKUI_CROSS__)
306     resourcePath_ = indexPath_.substr(0, index + 1);
307 #else
308     if (index < 1) {
309         return false;
310     }
311     index = indexPath_.rfind(separator, index - 1);
312     if (index == std::string::npos) {
313         RESMGR_HILOGE(RESMGR_TAG, "index path format error, %s", indexPath_.c_str());
314         return false;
315     }
316     resourcePath_ = indexPath_.substr(0, index + 1);
317 #endif
318     for (int i = 0; i < ResType::MAX_RES_TYPE; ++i) {
319         auto mptr = std::make_shared<std::map<std::string, std::shared_ptr<IdValues>>>();
320         idValuesNameMap_.push_back(mptr);
321     }
322     return InitIdList(defaultConfig);
323 }
324 
InitMap(const std::shared_ptr<ResKey> & resKey,const std::pair<std::string,std::string> & resPath,std::shared_ptr<ResConfigImpl> & defaultConfig)325 bool HapResource::InitMap(const std::shared_ptr<ResKey> &resKey, const std::pair<std::string, std::string> &resPath,
326     std::shared_ptr<ResConfigImpl> &defaultConfig)
327 {
328     for (size_t j = 0; j < resKey->resId_->idParams_.size(); ++j) {
329         std::shared_ptr<IdParam> idParam = resKey->resId_->idParams_[j];
330         uint32_t id = idParam->id_;
331         std::map<uint32_t, std::shared_ptr<IdValues>>::iterator iter = idValuesMap_.find(id);
332         if (iter == idValuesMap_.end()) {
333             auto idValues = std::make_shared<HapResource::IdValues>();
334             if (idValues == nullptr) {
335                 RESMGR_HILOGE(RESMGR_TAG, "new IdValues failed in HapResource::InitIdList");
336                 return false;
337             }
338             auto limitPath = std::make_shared<HapResource::ValueUnderQualifierDir>(resKey,
339                 idParam->idItem_, resPath, isOverlay_, isSystem_);
340             if (limitPath == nullptr) {
341                 RESMGR_HILOGE(RESMGR_TAG, "new ValueUnderQualifierDir failed in HapResource::InitIdList");
342                 return false;
343             }
344             idValues->AddLimitPath(limitPath);
345             HapResource::IsAppDarkRes(limitPath, defaultConfig);
346             idValuesMap_.insert(std::make_pair(id, idValues));
347             std::string name = std::string(idParam->idItem_->name_);
348             idValuesNameMap_[idParam->idItem_->resType_]->insert(std::make_pair(name, idValues));
349             if (name == "system_color_change" && idParam->idItem_->value_ == "true") {
350                 isThemeSystemResEnable_ = true;
351             }
352         } else {
353             std::shared_ptr<HapResource::IdValues> idValues = iter->second;
354             auto limitPath = std::make_shared<HapResource::ValueUnderQualifierDir>(resKey,
355                 idParam->idItem_, resPath, isOverlay_, isSystem_);
356             if (limitPath == nullptr) {
357                 RESMGR_HILOGE(RESMGR_TAG, "new ValueUnderQualifierDir failed in HapResource::InitIdList");
358                 return false;
359             }
360             idValues->AddLimitPath(limitPath);
361             HapResource::IsAppDarkRes(limitPath, defaultConfig);
362         }
363     }
364     return true;
365 }
366 
InitIdList(std::shared_ptr<ResConfigImpl> & defaultConfig)367 bool HapResource::InitIdList(std::shared_ptr<ResConfigImpl> &defaultConfig)
368 {
369     if (resDesc_ == nullptr) {
370         RESMGR_HILOGE(RESMGR_TAG, "resDesc_ is null ! InitIdList failed");
371         return false;
372     }
373     const auto resPath = std::make_pair(indexPath_, resourcePath_);
374     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
375         const auto resKey = resDesc_->keys_[i];
376         if (!HapResource::InitMap(resKey, resPath, defaultConfig)) {
377             return false;
378         }
379     }
380     return true;
381 };
382 
GetIdValues(const uint32_t id) const383 const std::shared_ptr<HapResource::IdValues> HapResource::GetIdValues(const uint32_t id) const
384 {
385     if (idValuesMap_.empty()) {
386         RESMGR_HILOGE(RESMGR_TAG, "idValuesMap_ is empty");
387         return nullptr;
388     }
389     uint32_t uid = id;
390     std::map<uint32_t, std::shared_ptr<IdValues>>::const_iterator iter = idValuesMap_.find(uid);
391     if (iter == idValuesMap_.end()) {
392         return nullptr;
393     }
394 
395     return iter->second;
396 }
397 
GetIdValuesByName(const std::string name,const ResType resType) const398 const std::shared_ptr<HapResource::IdValues> HapResource::GetIdValuesByName(
399     const std::string name, const ResType resType) const
400 {
401     const auto map = idValuesNameMap_[resType];
402     std::map<std::string, std::shared_ptr<IdValues>>::const_iterator iter = map->find(name);
403     if (iter == map->end()) {
404         return nullptr;
405     }
406 
407     return iter->second;
408 }
409 
GetIdByName(const char * name,const ResType resType) const410 int HapResource::GetIdByName(const char *name, const ResType resType) const
411 {
412     if (name == nullptr) {
413         return -1;
414     }
415     const auto map = idValuesNameMap_[resType];
416     std::map<std::string, std::shared_ptr<IdValues>>::const_iterator iter = map->find(name);
417     if (iter == map->end()) {
418         return OBJ_NOT_FOUND;
419     }
420     const std::shared_ptr<IdValues> ids = iter->second;
421 
422     if (ids->GetLimitPathsConst().size() == 0) {
423         RESMGR_HILOGE(RESMGR_TAG, "limitPaths empty");
424         return UNKNOWN_ERROR;
425     }
426 
427     if (ids->GetLimitPathsConst()[0]->GetIdItem()->resType_ != resType) {
428         RESMGR_HILOGE(RESMGR_TAG, "ResType mismatch");
429         return UNKNOWN_ERROR;
430     }
431     return ids->GetLimitPathsConst()[0]->GetIdItem()->id_;
432 }
433 
GetQualifiers() const434 const std::vector<std::string> HapResource::GetQualifiers() const
435 {
436     std::vector<std::string> result;
437     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
438         result.push_back(resDesc_->keys_[i]->ToString());
439     }
440     return result;
441 }
442 
GetResourceLimitKeys() const443 uint32_t HapResource::GetResourceLimitKeys() const
444 {
445     uint32_t limitKeyValue = 0;
446     std::vector<bool> keyTypes(KeyType::KEY_TYPE_MAX - 1, false);
447     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
448         if (iter->second == nullptr) {
449             continue;
450         }
451         const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &limitPaths = iter->second->GetLimitPathsConst();
452         if (limitPaths.size() <= 0) {
453             continue;
454         }
455         limitKeyValue |= GetLimitPathsKeys(limitPaths, keyTypes);
456     }
457     return limitKeyValue;
458 }
459 
GetLimitPathsKeys(const std::vector<std::shared_ptr<ValueUnderQualifierDir>> & limitPaths,std::vector<bool> & keyTypes) const460 uint32_t HapResource::GetLimitPathsKeys(const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &limitPaths,
461     std::vector<bool> &keyTypes) const
462 {
463     uint32_t limitKeyValue = 0;
464     const uint32_t limitKeysBase = 0x00000001;
465     for_each(limitPaths.begin(), limitPaths.end(), [&](auto &item) {
466         const std::vector<std::shared_ptr<KeyParam>> &keyParams = item->keyParams_;
467         for_each(keyParams.begin(), keyParams.end(), [&](auto &keyParam) {
468             uint32_t typeValue = static_cast<uint32_t>(keyParam->type_);
469             if (keyParam->type_ < KeyType::KEY_TYPE_MAX && !keyTypes[typeValue]) {
470                 keyTypes[typeValue] = true;
471                 limitKeyValue |= limitKeysBase << typeValue;
472             }
473         });
474     });
475     return limitKeyValue;
476 }
477 
GetLocales(std::set<std::string> & outValue,bool includeSystem)478 void HapResource::GetLocales(std::set<std::string> &outValue, bool includeSystem)
479 {
480     if ((!includeSystem && isSystem_) || (!isSystem_ && isOverlay_)) {
481         return;
482     }
483     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
484         GetKeyParamsLocales(resDesc_->keys_[i]->keyParams_, outValue);
485     }
486 }
487 
GetKeyParamsLocales(const std::vector<std::shared_ptr<KeyParam>> keyParams,std::set<std::string> & outValue)488 void HapResource::GetKeyParamsLocales(const std::vector<std::shared_ptr<KeyParam>> keyParams,
489     std::set<std::string> &outValue)
490 {
491     std::string locale;
492     bool isLocale = false;
493     for (size_t i = 0; i < keyParams.size(); i++) {
494         KeyType keyType = keyParams[i]->type_;
495         if (keyType == KeyType::MCC || keyType == KeyType::MNC) {
496             continue;
497         }
498         if (keyType == KeyType::LANGUAGES) {
499             locale = keyParams[i]->GetStr();
500             isLocale = true;
501             continue;
502         }
503         if (keyType == KeyType::SCRIPT) {
504             locale.append("-");
505             locale.append(keyParams[i]->GetStr());
506             continue;
507         }
508         if (keyType == KeyType::REGION) {
509             locale.append("-");
510             locale.append(keyParams[i]->GetStr());
511             break;
512         }
513         break;
514     }
515     if (isLocale) {
516         outValue.emplace(locale);
517     }
518 }
IsThemeSystemResEnable() const519 bool HapResource::IsThemeSystemResEnable() const
520 {
521     return this->isThemeSystemResEnable_;
522 }
523 
IsAppDarkRes(const std::shared_ptr<HapResource::ValueUnderQualifierDir> & limitPath,std::shared_ptr<ResConfigImpl> & defaultConfig)524 void HapResource::IsAppDarkRes(const std::shared_ptr<HapResource::ValueUnderQualifierDir> &limitPath,
525     std::shared_ptr<ResConfigImpl> &defaultConfig)
526 {
527     if (!defaultConfig) {
528         return;
529     }
530     if (isSystem_ || isOverlay_ || defaultConfig->GetAppDarkRes()) {
531         return;
532     }
533     std::string folder = limitPath->GetFolder();
534     if (folder.find("dark") != std::string::npos) {
535         defaultConfig->SetAppDarkRes(true);
536     }
537 }
538 } // namespace Resource
539 } // namespace Global
540 } // namespace OHOS
541