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