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