• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "hap_manager.h"
16 
17 #include <algorithm>
18 #include <fstream>
19 #include <climits>
20 #include <cstdlib>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include "utils/errors.h"
24 #ifdef SUPPORT_GRAPHICS
25 #include <ohos/init_data.h>
26 #include <unicode/unistr.h>
27 #include <unicode/utypes.h>
28 #endif
29 
30 #include "auto_mutex.h"
31 #include "hilog_wrapper.h"
32 
33 #include "hap_parser.h"
34 #include "utils/utils.h"
35 
36 #ifdef __WINNT__
37 #include <shlwapi.h>
38 #include <windows.h>
39 #else
40 #include <dlfcn.h>
41 #endif
42 
43 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
44 #include "hisysevent_adapter.h"
45 #endif
46 
47 namespace OHOS {
48 namespace Global {
49 namespace Resource {
50 #ifdef SUPPORT_GRAPHICS
51 constexpr uint32_t PLURAL_CACHE_MAX_COUNT = 3;
52 #endif
HapManager(ResConfigImpl * resConfig)53 HapManager::HapManager(ResConfigImpl *resConfig)
54     : resConfig_(resConfig)
55 {
56 }
57 
58 bool HapManager::icuInitialized = HapManager::Init();
59 
Init()60 bool HapManager::Init()
61 {
62 #ifdef SUPPORT_GRAPHICS
63 #ifdef __IDE_PREVIEW__
64 #ifdef __WINNT__
65     MEMORY_BASIC_INFORMATION mbi;
66     if (::VirtualQuery((LPCVOID)SetHwIcuDirectory, &mbi, sizeof(mbi)) != 0) {
67         char path[MAX_PATH] = { 0 };
68         GetModuleFileName((HMODULE)mbi.AllocationBase, path, MAX_PATH);
69         std::string tempPath(path);
70         auto pos = tempPath.rfind('\\');
71         if (pos != std::string::npos) {
72             u_setDataDirectory(tempPath.substr(0, pos).c_str());
73         }
74     }
75 #else
76     Dl_info info;
77     if (dladdr((void*)SetHwIcuDirectory, &info) != 0) {
78         std::string tempPath(info.dli_fname);
79         auto pos = tempPath.rfind('/');
80         if (pos != std::string::npos) {
81             u_setDataDirectory(tempPath.substr(0, pos).c_str());
82         }
83     }
84 #endif
85 #else
86 #if !defined(__ARKUI_CROSS__)
87     SetHwIcuDirectory();
88 #endif
89 #endif
90 #endif
91     return true;
92 }
93 
GetPluralRulesAndSelect(int quantity)94 std::string HapManager::GetPluralRulesAndSelect(int quantity)
95 {
96     std::string defaultRet("other");
97 #ifdef SUPPORT_GRAPHICS
98     AutoMutex mutex(this->lock_);
99     if (this->resConfig_ == nullptr || this->resConfig_->GetResLocale() == nullptr ||
100         this->resConfig_->GetResLocale()->GetLanguage() == nullptr) {
101         HILOG_ERROR("GetPluralRules language is null!");
102         return defaultRet;
103     }
104     std::string language = this->resConfig_->GetResLocale()->GetLanguage();
105 
106     icu::PluralRules *pluralRules = nullptr;
107     for (uint32_t i = 0; i < plurRulesCache_.size(); i++) {
108         auto pair = plurRulesCache_[i];
109         if (language == pair.first) {
110             // cache hit
111             pluralRules = pair.second;
112             break;
113         }
114     }
115 
116     if (pluralRules == nullptr) {
117         // no cache hit
118         icu::Locale locale(language.c_str());
119         if (locale.isBogus()) {
120             HILOG_ERROR("icu::Locale init error : %s", language.c_str());
121             return defaultRet;
122         }
123         UErrorCode status = U_ZERO_ERROR;
124         pluralRules = icu::PluralRules::forLocale(locale, status);
125         if (status != U_ZERO_ERROR) {
126             HILOG_ERROR("icu::PluralRules::forLocale error : %d", status);
127             return defaultRet;
128         }
129         // after PluralRules created, we add it to cache, if > 3 delete oldest one
130         if (plurRulesCache_.size() >= PLURAL_CACHE_MAX_COUNT) {
131             HILOG_DEBUG("cache rotate delete plurRulesMap_ %s", plurRulesCache_[0].first.c_str());
132             delete (plurRulesCache_[0].second);
133             plurRulesCache_.erase(plurRulesCache_.begin());
134         }
135         auto plPair = std::make_pair(language, pluralRules);
136         plurRulesCache_.push_back(plPair);
137     }
138     std::string converted;
139     icu::UnicodeString us = pluralRules->select(quantity);
140     us.toUTF8String(converted);
141     return converted;
142 #else
143     return defaultRet;
144 #endif
145 }
146 
FindResourceById(uint32_t id)147 const IdItem *HapManager::FindResourceById(uint32_t id)
148 {
149     auto qualifierValue = FindQualifierValueById(id);
150     if (qualifierValue == nullptr) {
151         return nullptr;
152     }
153     return qualifierValue->GetIdItem();
154 }
155 
FindResourceByName(const char * name,const ResType resType)156 const IdItem *HapManager::FindResourceByName(const char *name, const ResType resType)
157 {
158     auto qualifierValue = FindQualifierValueByName(name, resType);
159     if (qualifierValue == nullptr) {
160         return nullptr;
161     }
162     return qualifierValue->GetIdItem();
163 }
164 
FindQualifierValueByName(const char * name,const ResType resType,uint32_t density)165 const HapResource::ValueUnderQualifierDir *HapManager::FindQualifierValueByName(
166     const char *name, const ResType resType, uint32_t density)
167 {
168     AutoMutex mutex(this->lock_);
169     std::vector<const HapResource::IdValues *> candidates = this->GetResourceListByName(name, resType);
170     if (candidates.size() == 0) {
171         return nullptr;
172     }
173     return this->GetBestMatchResource(candidates, density);
174 }
175 
FindQualifierValueById(uint32_t id,uint32_t density)176 const HapResource::ValueUnderQualifierDir *HapManager::FindQualifierValueById(uint32_t id, uint32_t density)
177 {
178     AutoMutex mutex(this->lock_);
179     std::vector<const HapResource::IdValues *> candidates = this->GetResourceList(id);
180     if (candidates.size() == 0) {
181         return nullptr;
182     }
183     return this->GetBestMatchResource(candidates, density);
184 }
185 
GetBestMatchResource(std::vector<const HapResource::IdValues * > candidates,uint32_t density)186 const HapResource::ValueUnderQualifierDir *HapManager::GetBestMatchResource(std::vector<const HapResource::IdValues *>
187     candidates, uint32_t density)
188 {
189     const ResConfigImpl *bestResConfig = nullptr;
190     const ResConfigImpl *bestOverlayResConfig = nullptr;
191     const HapResource::ValueUnderQualifierDir *result = nullptr;
192     const HapResource::ValueUnderQualifierDir *overlayResult = nullptr;
193     const ResConfigImpl *currentResConfig = this->resConfig_;
194     for (auto iter = candidates.begin(); iter != candidates.end(); iter++) {
195         const std::vector<HapResource::ValueUnderQualifierDir *> paths = (*iter)->GetLimitPathsConst();
196         size_t len = paths.size();
197         size_t i = 0;
198         bool isOverlayHapResource = paths[0]->IsOverlay();
199         for (i = 0; i < len; i++) {
200             HapResource::ValueUnderQualifierDir *path = paths[i];
201             const ResConfigImpl *resConfig = path->GetResConfig();
202             if (!this->resConfig_->Match(resConfig)) {
203                 continue;
204             }
205             if (isOverlayHapResource) {
206                 if (bestOverlayResConfig == nullptr) {
207                     bestOverlayResConfig = resConfig;
208                     overlayResult = paths[i];
209                     continue;
210                 }
211                 if (!bestOverlayResConfig->IsMoreSuitable(resConfig, currentResConfig, density)) {
212                     bestOverlayResConfig = resConfig;
213                     overlayResult = paths[i];
214                 }
215             } else {
216                 if (bestResConfig == nullptr) {
217                     bestResConfig = resConfig;
218                     result = paths[i];
219                     continue;
220                 }
221                 if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig, density)) {
222                     bestResConfig = resConfig;
223                     result = paths[i];
224                 }
225             }
226         }
227     }
228     if (bestOverlayResConfig != nullptr && result != nullptr && result->IsSystemResource()) {
229         if (bestOverlayResConfig->IsMoreSuitable(bestResConfig, currentResConfig, density)) {
230             return overlayResult;
231         }
232     }
233     return result;
234 }
235 
FindRawFile(const std::string & name,std::string & outValue)236 RState HapManager::FindRawFile(const std::string &name, std::string &outValue)
237 {
238 #ifdef __WINNT__
239     char seperator = '\\';
240 #else
241     char seperator = '/';
242 #endif
243     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
244         std::string indexPath = (*iter)->GetIndexPath();
245         auto index = indexPath.rfind(seperator);
246         if (index == std::string::npos) {
247             HILOG_ERROR("index path format error, %s", indexPath.c_str());
248             continue;
249         }
250         std::string resourcesIndexPath = indexPath.substr(0, index);
251         char tmpPath[PATH_MAX] = {0};
252         std::string tempName = name;
253         const std::string rawFileDirName = "rawfile/";
254         if (tempName.length() <= rawFileDirName.length()
255             || (tempName.compare(0, rawFileDirName.length(), rawFileDirName) != 0)) {
256             tempName = rawFileDirName + tempName;
257         }
258 #ifdef __WINNT__
259         if (!PathCanonicalizeA(tmpPath, (resourcesIndexPath + "/resources/" + tempName).c_str())) {
260             continue;
261         }
262 #else
263         if (realpath((resourcesIndexPath + "/resources/" + tempName).c_str(), tmpPath) == nullptr) {
264             HILOG_ERROR("FindRawFile path to realpath error");
265             continue;
266         }
267 #endif
268         const std::string realPath = tmpPath;
269         if (realPath.length() > resourcesIndexPath.length()
270             && (realPath.compare(0, resourcesIndexPath.length(), resourcesIndexPath) == 0)) {
271             std::fstream inputFile;
272             inputFile.open(realPath, std::ios::in);
273             if (inputFile) {
274                 outValue = realPath;
275                 return SUCCESS;
276             }
277         }
278     }
279     return ERROR_CODE_RES_PATH_INVALID;
280 }
281 
UpdateResConfig(ResConfig & resConfig)282 RState HapManager::UpdateResConfig(ResConfig &resConfig)
283 {
284     AutoMutex mutex(this->lock_);
285     this->resConfig_->Copy(resConfig);
286     RState rState = this->ReloadAll();
287     if (rState != SUCCESS) {
288         HILOG_ERROR("ReloadAll() failed when UpdateResConfig!");
289     }
290     return rState;
291 }
292 
293 
GetResConfig(ResConfig & resConfig)294 void HapManager::GetResConfig(ResConfig &resConfig)
295 {
296     AutoMutex mutex(this->lock_);
297     resConfig.Copy(*(this->resConfig_));
298 }
299 
AddResource(const char * path)300 bool HapManager::AddResource(const char *path)
301 {
302     AutoMutex mutex(this->lock_);
303     return this->AddResourcePath(path);
304 }
305 
AddResource(const std::string & path,const std::vector<std::string> & overlayPaths)306 bool HapManager::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
307 {
308     loadedHapPaths_[path] = overlayPaths;
309     std::unordered_map<std::string, HapResource *> result = HapResource::LoadOverlays(path, overlayPaths, resConfig_);
310     if (result.size() > 0) {
311         std::vector<std::string> &validOverlayPaths = loadedHapPaths_[path];
312         int i = 0;
313         for (auto iter = result.begin(); iter != result.end(); iter++) {
314             this->hapResources_.push_back(iter->second);
315             if (i > 0) {
316                 // the first is the target, not the overlay
317                 validOverlayPaths.push_back(iter->first);
318                 i++;
319             }
320         }
321         return true;
322     }
323     return false;
324 }
325 
~HapManager()326 HapManager::~HapManager()
327 {
328     for (size_t i = 0; i < hapResources_.size(); ++i) {
329         if (hapResources_[i] != nullptr) {
330             delete hapResources_[i];
331             hapResources_[i] = nullptr;
332         }
333     }
334     if (resConfig_ != nullptr) {
335         delete resConfig_;
336         resConfig_ = nullptr;
337     }
338 
339 #ifdef SUPPORT_GRAPHICS
340     auto iter = plurRulesCache_.begin();
341     for (; iter != plurRulesCache_.end(); iter++) {
342         HILOG_DEBUG("delete plurRulesMap_ %s", iter->first.c_str());
343         if (iter->second != nullptr) {
344             auto ptr = iter->second;
345             delete (ptr);
346             iter->second = nullptr;
347         }
348     }
349 #endif
350 }
351 
GetResourceList(uint32_t ident) const352 std::vector<const HapResource::IdValues *> HapManager::GetResourceList(uint32_t ident) const
353 {
354     std::vector<const HapResource::IdValues *> result;
355     // one id only exit in one hap
356     for (size_t i = 0; i < hapResources_.size(); ++i) {
357         HapResource *pResource = hapResources_[i];
358         const HapResource::IdValues *out = pResource->GetIdValues(ident);
359         if (out != nullptr) {
360             result.emplace_back(out);
361         }
362     }
363     return result;
364 }
365 
GetResourceListByName(const char * name,const ResType resType) const366 std::vector<const HapResource::IdValues *> HapManager::GetResourceListByName(const char *name,
367     const ResType resType) const
368 {
369     std::vector<const HapResource::IdValues *> result;
370     // all match will return
371     for (size_t i = 0; i < hapResources_.size(); ++i) {
372         HapResource *pResource = hapResources_[i];
373         const HapResource::IdValues *out = pResource->GetIdValuesByName(std::string(name), resType);
374         if (out != nullptr) {
375             result.emplace_back(out);
376         }
377     }
378     return result;
379 }
380 
AddResourcePath(const char * path)381 bool HapManager::AddResourcePath(const char *path)
382 {
383     std::string sPath(path);
384     auto it = loadedHapPaths_.find(sPath);
385     if (it != loadedHapPaths_.end()) {
386         HILOG_ERROR(" %s has already been loaded!", path);
387         return false;
388     }
389     const HapResource *pResource = HapResource::Load(path, resConfig_);
390     if (pResource == nullptr) {
391 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
392         ReportAddResourcePathFail(path, "AddResourcePath failed");
393 #endif
394         return false;
395     }
396     this->hapResources_.push_back(const_cast<HapResource *>(pResource));
397     this->loadedHapPaths_[sPath] = std::vector<std::string>();
398     return true;
399 }
400 
DeleteNewResource(std::vector<HapResource * > & newResources)401 void DeleteNewResource(std::vector<HapResource *> &newResources)
402 {
403     for (size_t i = 0; i < newResources.size(); ++i) {
404         if (newResources[i] != nullptr) {
405             delete (newResources[i]);
406             newResources[i] = nullptr;
407         }
408     }
409 }
410 
ReloadAll()411 RState HapManager::ReloadAll()
412 {
413     if (hapResources_.size() == 0) {
414         return SUCCESS;
415     }
416     std::vector<HapResource *> newResources;
417     for (auto iter = loadedHapPaths_.begin(); iter != loadedHapPaths_.end(); iter++) {
418         std::vector<std::string> &overlayPaths = iter->second;
419         if (overlayPaths.size() == 0) {
420             const HapResource *pResource = HapResource::Load(iter->first.c_str(), resConfig_);
421             if (pResource == nullptr) {
422                 DeleteNewResource(newResources);
423                 return HAP_INIT_FAILED;
424             }
425             newResources.push_back(const_cast<HapResource *>(pResource));
426             continue;
427         }
428         std::unordered_map<std::string, HapResource *> result = HapResource::LoadOverlays(iter->first.c_str(),
429             overlayPaths, resConfig_);
430         if (result.size() == 0) {
431             continue;
432         }
433         for (auto iter = result.begin(); iter != result.end(); iter++) {
434             newResources.push_back(iter->second);
435         }
436     }
437     for (size_t i = 0; i < hapResources_.size(); ++i) {
438         delete (hapResources_[i]);
439     }
440     hapResources_ = newResources;
441     return SUCCESS;
442 }
443 
GetResourcePaths()444 std::vector<std::string> HapManager::GetResourcePaths()
445 {
446     std::vector<std::string> result;
447     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
448         std::string indexPath = (*iter)->GetIndexPath();
449         auto index = indexPath.rfind('/');
450         if (index == std::string::npos) {
451             HILOG_ERROR("index path format error, %s", indexPath.c_str());
452             continue;
453         }
454 
455         result.emplace_back(indexPath.substr(0, index) + "/resources/");
456     }
457 
458     return result;
459 }
460 
IsLoadHap()461 bool HapManager::IsLoadHap()
462 {
463     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
464         if ((*iter) == nullptr) {
465             HILOG_ERROR("the hapResource_ is nullptr");
466             return false;
467         }
468         const std::string hapPath = (*iter)->GetIndexPath();
469         if (Utils::ContainsTail(hapPath, Utils::tailSet)) {
470             return true;
471         }
472     }
473     return false;
474 }
475 
GetFilePath(const HapResource::ValueUnderQualifierDir * qd,unzFile & uf,const ResType resType)476 std::string GetFilePath(const HapResource::ValueUnderQualifierDir *qd, unzFile &uf, const ResType resType)
477 {
478     std::string filePath;
479     if (qd == nullptr) {
480         return filePath;
481     }
482     const IdItem *idItem = qd->GetIdItem();
483     if (idItem == nullptr || idItem->resType_ != resType) {
484         return filePath;
485     }
486     if (HapParser::IsStageMode(uf)) {
487         std::string tempFilePath(idItem->value_);
488         auto index = tempFilePath.find('/');
489         if (index == std::string::npos) {
490             HILOG_ERROR("resource path format error, %s", tempFilePath.c_str());
491             return filePath;
492         }
493         filePath = idItem->value_.substr(index + 1);
494     } else {
495         // FA mode
496         std::string tempFilePath("assets/");
497         tempFilePath.append(idItem->value_);
498         filePath = tempFilePath;
499     }
500     return filePath;
501 }
502 
GetImageType(const std::string fileName)503 std::string GetImageType(const std::string fileName)
504 {
505     auto pos = fileName.find_last_of('.');
506     std::string imgType;
507     if (pos != std::string::npos) {
508         imgType = fileName.substr(pos + 1);
509     }
510     return imgType;
511 }
512 
GetHapUf(const HapResource::ValueUnderQualifierDir * qd)513 unzFile GetHapUf(const HapResource::ValueUnderQualifierDir *qd)
514 {
515     std::string hapPath = qd->GetHapResource()->GetIndexPath();
516     unzFile uf = unzOpen64(hapPath.c_str()); // open zipfile stream
517     if (uf == nullptr) {
518         HILOG_ERROR("Open the %{public}s failed in GetHapUf", hapPath.c_str());
519         return nullptr;
520     } // file is open
521     return uf;
522 }
523 
GetProfileData(const HapResource::ValueUnderQualifierDir * qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)524 RState HapManager::GetProfileData(const HapResource::ValueUnderQualifierDir *qd, size_t &len,
525     std::unique_ptr<uint8_t[]> &outValue)
526 {
527     unzFile uf = GetHapUf(qd);
528     if (uf == nullptr) {
529         return NOT_FOUND;
530     }
531     std::string filePath = GetFilePath(qd, uf, ResType::PROF);
532     int err = HapParser::ReadFileFromZip(uf, filePath.c_str(), outValue, len);
533     if (err < 0) {
534         unzClose(uf);
535         return NOT_FOUND;
536     }
537     unzClose(uf);
538     return SUCCESS;
539 }
540 
GetMediaData(const HapResource::ValueUnderQualifierDir * qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)541 RState HapManager::GetMediaData(const HapResource::ValueUnderQualifierDir *qd, size_t &len,
542     std::unique_ptr<uint8_t[]> &outValue)
543 {
544     unzFile uf = GetHapUf(qd);
545     if (uf == nullptr) {
546         return NOT_FOUND;
547     }
548     std::string filePath = GetFilePath(qd, uf, ResType::MEDIA);
549     int err = HapParser::ReadFileFromZip(uf, filePath.c_str(), outValue, len);
550     if (err < 0) {
551         unzClose(uf);
552         return NOT_FOUND;
553     }
554     unzClose(uf);
555     return SUCCESS;
556 }
557 
GetMediaBase64Data(const HapResource::ValueUnderQualifierDir * qd,std::string & outValue)558 RState HapManager::GetMediaBase64Data(const HapResource::ValueUnderQualifierDir *qd, std::string &outValue)
559 {
560     unzFile uf = GetHapUf(qd);
561     if (uf == nullptr) {
562         return NOT_FOUND;
563     }
564     std::string filePath = GetFilePath(qd, uf, ResType::MEDIA);
565     std::unique_ptr<uint8_t[]> buffer;
566     size_t tmpLen;
567     int err = HapParser::ReadFileFromZip(uf, filePath.c_str(), buffer, tmpLen);
568     if (err < 0) {
569         unzClose(uf);
570         return NOT_FOUND;
571     }
572     std::string imgType = GetImageType(filePath);
573     Utils::EncodeBase64(buffer, tmpLen, imgType, outValue);
574     unzClose(uf);
575     return SUCCESS;
576 }
577 
GetFileFd(const char * zipFile,std::unique_ptr<ResourceManager::RawFile> & rawFile)578 int32_t GetFileFd(const char *zipFile, std::unique_ptr<ResourceManager::RawFile> &rawFile)
579 {
580     int zipFd = open(zipFile, O_RDONLY);
581     if (zipFd < 0) {
582         HILOG_ERROR("open file failed in GetFileFd");
583         return UNKNOWN_ERROR;
584     }
585     FILE *file = fdopen(zipFd, "r");
586     if (file == nullptr) {
587         HILOG_ERROR("fdopen the fd failed in GetFileFd");
588         close(zipFd);
589         return UNKNOWN_ERROR;
590     }
591     rawFile->pf = file;
592     return OK;
593 }
594 
FindRawFileFromHap(const std::string & rawFileName,std::unique_ptr<ResourceManager::RawFile> & rawFile)595 RState HapManager::FindRawFileFromHap(const std::string &rawFileName,
596     std::unique_ptr<ResourceManager::RawFile> &rawFile)
597 {
598     if (rawFile == nullptr) {
599         rawFile = std::make_unique<ResourceManager::RawFile>();
600     }
601     const std::string sysResHap = "SystemResources.hap";
602     for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
603         const std::string hapPath = (*iter)->GetIndexPath();
604         if (hapPath.find(sysResHap) != std::string::npos) {
605             continue;
606         }
607         if (Utils::ContainsTail(hapPath, Utils::tailSet)) {
608             size_t tmpLen;
609             int32_t ret = HapParser::ReadRawFileFromHap(hapPath.c_str(), rawFile->buffer, tmpLen, rawFileName, rawFile);
610             if (ret != OK) {
611                 continue;
612             }
613             ret = GetFileFd(hapPath.c_str(), rawFile);
614             if (ret != OK) {
615                 return ERROR_CODE_RES_PATH_INVALID;
616             }
617             rawFile->length = static_cast<long>(tmpLen);
618             return SUCCESS;
619         }
620     }
621     return ERROR_CODE_RES_PATH_INVALID;
622 }
623 } // namespace Resource
624 } // namespace Global
625 } // namespace OHOS
626