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