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