1 /*
2 * Copyright (c) 2021-2025 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 #include "hap_resource_manager.h"
17
18 #include <algorithm>
19 #include <fstream>
20 #include <climits>
21 #include <cstdlib>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <tuple>
25 #include <set>
26 #include "utils/errors.h"
27 #ifdef SUPPORT_GRAPHICS
28 #include <ohos/init_data.h>
29 #include <unicode/unistr.h>
30 #include <unicode/utypes.h>
31 #endif
32
33 #include "hilog_wrapper.h"
34
35 #include "hap_parser.h"
36 #include "utils/utils.h"
37 #include "res_common.h"
38
39 #ifdef __WINNT__
40 #include <shlwapi.h>
41 #include <windows.h>
42 #else
43 #include <dlfcn.h>
44 #endif
45
46 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
47 #include "hitrace_meter.h"
48 #include "hisysevent_adapter.h"
49 #include "file_mapper.h"
50 #include "extractor.h"
51 #endif
52
53 namespace OHOS {
54 namespace Global {
55 namespace Resource {
56 #ifdef SUPPORT_GRAPHICS
57 constexpr uint32_t PLURAL_CACHE_MAX_COUNT = 3;
58 #endif
59 #if defined(__ARKUI_CROSS__) || defined(__WINNT__) || defined(__IDE_PREVIEW__)
60 const std::string RAW_FILE_PATH = "resources/rawfile/";
61 #endif
62
63 using ReadLock = std::shared_lock<std::shared_mutex>;
64 using WriteLock = std::unique_lock<std::shared_mutex>;
65
66 std::mutex g_rawFileLock;
67
HapManager(std::shared_ptr<ResConfigImpl> resConfig,bool isSystem)68 HapManager::HapManager(std::shared_ptr<ResConfigImpl> resConfig, bool isSystem)
69 : resConfig_(resConfig), isSystem_(isSystem)
70 {
71 overrideResConfig_->SetColorMode(COLOR_MODE_NOT_SET);
72 }
73
HapManager(std::shared_ptr<ResConfigImpl> resConfig,std::vector<std::shared_ptr<HapResource>> hapResources,std::unordered_map<std::string,std::vector<std::string>> loadedHapPaths,bool isSystem)74 HapManager::HapManager(std::shared_ptr<ResConfigImpl> resConfig, std::vector<std::shared_ptr<HapResource>> hapResources,
75 std::unordered_map<std::string, std::vector<std::string>> loadedHapPaths, bool isSystem)
76 : resConfig_(resConfig), hapResources_(hapResources), loadedHapPaths_(loadedHapPaths), isSystem_(isSystem)
77 {
78 overrideResConfig_->SetColorMode(COLOR_MODE_NOT_SET);
79 }
80
81 bool HapManager::icuInitialized = HapManager::Init();
82
Init()83 bool HapManager::Init()
84 {
85 #ifdef SUPPORT_GRAPHICS
86 #ifdef __IDE_PREVIEW__
87 #ifdef __WINNT__
88 MEMORY_BASIC_INFORMATION mbi;
89 if (::VirtualQuery((LPCVOID)SetHwIcuDirectory, &mbi, sizeof(mbi)) != 0) {
90 char path[MAX_PATH] = { 0 };
91 GetModuleFileName((HMODULE)mbi.AllocationBase, path, MAX_PATH);
92 std::string tempPath(path);
93 auto pos = tempPath.rfind('\\');
94 if (pos != std::string::npos) {
95 u_setDataDirectory(tempPath.substr(0, pos).c_str());
96 }
97 }
98 #else
99 Dl_info info;
100 if (dladdr((void*)SetHwIcuDirectory, &info) != 0) {
101 std::string tempPath(info.dli_fname);
102 auto pos = tempPath.rfind('/');
103 if (pos != std::string::npos) {
104 u_setDataDirectory(tempPath.substr(0, pos).c_str());
105 }
106 }
107 #endif
108 #else
109 #if !defined(__ARKUI_CROSS__)
110 SetHwIcuDirectory();
111 #endif
112 #endif
113 #endif
114 return true;
115 }
116
GetPluralRulesAndSelect(ResourceManager::Quantity quantity,bool isGetOverrideResource)117 std::string HapManager::GetPluralRulesAndSelect(ResourceManager::Quantity quantity, bool isGetOverrideResource)
118 {
119 std::string defaultRet("other");
120 #ifdef SUPPORT_GRAPHICS
121 WriteLock lock(this->mutex_);
122 std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isGetOverrideResource);
123 if (config == nullptr || config->GetResLocale() == nullptr ||
124 config->GetResLocale()->GetLanguage() == nullptr) {
125 RESMGR_HILOGE(RESMGR_TAG, "GetPluralRules language is null!");
126 return defaultRet;
127 }
128 std::string language = config->GetResLocale()->GetLanguage();
129
130 icu::PluralRules *pluralRules = nullptr;
131 for (uint32_t i = 0; i < plurRulesCache_.size(); i++) {
132 auto pair = plurRulesCache_[i];
133 if (language == pair.first) {
134 // cache hit
135 pluralRules = pair.second;
136 break;
137 }
138 }
139
140 if (pluralRules == nullptr) {
141 // no cache hit
142 icu::Locale locale(language.c_str());
143 if (locale.isBogus()) {
144 RESMGR_HILOGE(RESMGR_TAG, "icu::Locale init error : %s", language.c_str());
145 return defaultRet;
146 }
147 UErrorCode status = U_ZERO_ERROR;
148 pluralRules = icu::PluralRules::forLocale(locale, status);
149 if (status != U_ZERO_ERROR) {
150 RESMGR_HILOGE(RESMGR_TAG, "icu::PluralRules::forLocale error : %d", status);
151 return defaultRet;
152 }
153 // after PluralRules created, we add it to cache, if > 3 delete oldest one
154 if (plurRulesCache_.size() >= PLURAL_CACHE_MAX_COUNT) {
155 RESMGR_HILOGD(RESMGR_TAG, "cache rotate delete plurRulesMap_ %s", plurRulesCache_[0].first.c_str());
156 delete (plurRulesCache_[0].second);
157 plurRulesCache_.erase(plurRulesCache_.begin());
158 }
159 auto plPair = std::make_pair(language, pluralRules);
160 plurRulesCache_.push_back(plPair);
161 }
162 std::string converted;
163 icu::UnicodeString us = quantity.isInteger ? pluralRules->select(quantity.intValue) :
164 pluralRules->select(quantity.doubleValue);
165 us.toUTF8String(converted);
166 return converted;
167 #else
168 return defaultRet;
169 #endif
170 }
171
FindResourceById(uint32_t id,bool isGetOverrideResource)172 const std::shared_ptr<IdItem> HapManager::FindResourceById(uint32_t id, bool isGetOverrideResource)
173 {
174 auto qualifierValue = FindQualifierValueById(id, isGetOverrideResource);
175 if (qualifierValue == nullptr) {
176 return nullptr;
177 }
178 return qualifierValue->GetIdItem();
179 }
180
FindResourceByName(const char * name,const ResType resType,bool isGetOverrideResource)181 const std::shared_ptr<IdItem> HapManager::FindResourceByName(
182 const char *name, const ResType resType, bool isGetOverrideResource)
183 {
184 auto qualifierValue = FindQualifierValueByName(name, resType, isGetOverrideResource);
185 if (qualifierValue == nullptr) {
186 return nullptr;
187 }
188 return qualifierValue->GetIdItem();
189 }
190
FindQualifierValueByName(const char * name,const ResType resType,bool isGetOverrideResource,uint32_t density)191 const std::shared_ptr<ValueUnderQualifierDir> HapManager::FindQualifierValueByName(
192 const char *name, const ResType resType, bool isGetOverrideResource, uint32_t density)
193 {
194 ReadLock lock(this->mutex_);
195 std::vector<std::shared_ptr<IdValues>> candidates = this->GetResourceListByName(name, resType);
196 if (candidates.size() == 0) {
197 return nullptr;
198 }
199 return this->GetBestMatchResource(candidates, density, isGetOverrideResource);
200 }
201
FindQualifierValueById(uint32_t id,bool isGetOverrideResource,uint32_t density)202 const std::shared_ptr<ValueUnderQualifierDir> HapManager::FindQualifierValueById(uint32_t id,
203 bool isGetOverrideResource, uint32_t density)
204 {
205 ReadLock lock(this->mutex_);
206 std::vector<std::shared_ptr<IdValues>> candidates = this->GetResourceList(id);
207 if (candidates.size() == 0) {
208 return nullptr;
209 }
210 return this->GetBestMatchResource(candidates, density, isGetOverrideResource);
211 }
212
getCompleteOverrideConfig(bool isGetOverrideResource)213 std::shared_ptr<ResConfigImpl> HapManager::getCompleteOverrideConfig(bool isGetOverrideResource)
214 {
215 if (!isGetOverrideResource) {
216 return this->resConfig_;
217 }
218
219 std::shared_ptr<ResConfigImpl> completeOverrideConfig = std::make_shared<ResConfigImpl>();
220 if (!completeOverrideConfig || !this->resConfig_ || !this->overrideResConfig_) {
221 RESMGR_HILOGE(RESMGR_TAG, "completeOverrideConfig or resConfig_ or overrideResConfig_ is nullptr");
222 return nullptr;
223 }
224
225 if (!completeOverrideConfig->Copy(*this->resConfig_, true)) {
226 RESMGR_HILOGE(RESMGR_TAG, "getCompleteOverrideConfig copy failed");
227 return nullptr;
228 }
229
230 if (this->overrideResConfig_->isLocaleInfoSet()
231 && !completeOverrideConfig->CopyLocaleAndPreferredLocale(*this->overrideResConfig_)) {
232 RESMGR_HILOGE(RESMGR_TAG, "getCompleteOverrideConfig CopyLocaleAndPreferredLocale failed");
233 return nullptr;
234 }
235 if (this->overrideResConfig_->GetDeviceType() != DEVICE_NOT_SET) {
236 completeOverrideConfig->SetDeviceType(this->overrideResConfig_->GetDeviceType());
237 }
238 if (this->overrideResConfig_->GetDirection() != DIRECTION_NOT_SET) {
239 completeOverrideConfig->SetDirection(this->overrideResConfig_->GetDirection());
240 }
241 if (this->overrideResConfig_->GetColorMode() != COLOR_MODE_NOT_SET) {
242 completeOverrideConfig->SetColorMode(this->overrideResConfig_->GetColorMode());
243 }
244 if (this->overrideResConfig_->GetInputDevice() != INPUTDEVICE_NOT_SET) {
245 completeOverrideConfig->SetInputDevice(this->overrideResConfig_->GetInputDevice());
246 }
247 if (this->overrideResConfig_->GetMcc() != MCC_UNDEFINED) {
248 completeOverrideConfig->SetMcc(this->overrideResConfig_->GetMcc());
249 }
250 if (this->overrideResConfig_->GetMnc() != MNC_UNDEFINED) {
251 completeOverrideConfig->SetMnc(this->overrideResConfig_->GetMnc());
252 }
253 if (this->overrideResConfig_->GetScreenDensity() != SCREEN_DENSITY_NOT_SET) {
254 completeOverrideConfig->SetScreenDensity(this->overrideResConfig_->GetScreenDensity());
255 }
256 return completeOverrideConfig;
257 }
258
MatchBestResource(std::shared_ptr<ResConfigImpl> & bestResConfig,std::shared_ptr<ValueUnderQualifierDir> & result,const std::vector<std::shared_ptr<ValueUnderQualifierDir>> & paths,uint32_t density,std::shared_ptr<ResConfigImpl> currentResConfig)259 void HapManager::MatchBestResource(std::shared_ptr<ResConfigImpl> &bestResConfig,
260 std::shared_ptr<ValueUnderQualifierDir> &result,
261 const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &paths,
262 uint32_t density, std::shared_ptr<ResConfigImpl> currentResConfig)
263 {
264 size_t len = paths.size();
265 size_t i = 0;
266 for (i = 0; i < len; i++) {
267 std::shared_ptr<ValueUnderQualifierDir> path = paths[i];
268 const auto resConfig = path->GetResConfig();
269 if (!currentResConfig->Match(resConfig)) {
270 continue;
271 }
272 if (bestResConfig == nullptr) {
273 bestResConfig = resConfig;
274 result = paths[i];
275 continue;
276 }
277 if (!bestResConfig->IsMoreSuitable(resConfig, currentResConfig, density)) {
278 bestResConfig = resConfig;
279 result = paths[i];
280 }
281 }
282 }
283
GetBestMatchResource(const std::vector<std::shared_ptr<IdValues>> & candidates,uint32_t density,bool isGetOverrideResource)284 const std::shared_ptr<ValueUnderQualifierDir> HapManager::GetBestMatchResource(
285 const std::vector<std::shared_ptr<IdValues>> &candidates, uint32_t density, bool isGetOverrideResource)
286 {
287 std::shared_ptr<ResConfigImpl> bestResConfig = nullptr;
288 std::shared_ptr<ResConfigImpl> bestOverlayResConfig = nullptr;
289 std::shared_ptr<ValueUnderQualifierDir> result = nullptr;
290 std::shared_ptr<ValueUnderQualifierDir> overlayResult = nullptr;
291 const std::shared_ptr<ResConfigImpl> currentResConfig = getCompleteOverrideConfig(isGetOverrideResource);
292 if (!currentResConfig) {
293 return nullptr;
294 }
295 // When there are multiple overlays, reverse the search to find the first match resource.
296 for (auto iter = candidates.rbegin(); iter != candidates.rend(); iter++) {
297 const auto &paths = (*iter)->GetLimitPathsConst();
298 bool isOverlayHapResource = paths[0]->IsOverlayResource();
299 if (isOverlayHapResource) {
300 MatchBestResource(bestOverlayResConfig, overlayResult, paths, density, currentResConfig);
301 } else {
302 MatchBestResource(bestResConfig, result, paths, density, currentResConfig);
303 }
304 }
305 if (bestOverlayResConfig != nullptr && result != nullptr) {
306 if (bestOverlayResConfig->IsMoreSuitable(bestResConfig, currentResConfig, density)) {
307 return overlayResult;
308 }
309 }
310 return result;
311 }
312
FindRawFile(const std::string & name,std::string & outValue)313 RState HapManager::FindRawFile(const std::string &name, std::string &outValue)
314 {
315 #ifdef __WINNT__
316 char seperator = '\\';
317 #else
318 char seperator = '/';
319 #endif
320 ReadLock lock(this->mutex_);
321 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
322 std::string indexPath = (*iter)->GetIndexPath();
323 auto index = indexPath.rfind(seperator);
324 if (index == std::string::npos) {
325 RESMGR_HILOGE(RESMGR_TAG, "index path format error by seperator");
326 continue;
327 }
328 std::string resourcesIndexPath = indexPath.substr(0, index);
329 char tmpPath[PATH_MAX] = {0};
330 std::string tempName = name;
331 const std::string rawFileDirName = "rawfile/";
332 if (tempName.length() <= rawFileDirName.length()
333 || (tempName.compare(0, rawFileDirName.length(), rawFileDirName) != 0)) {
334 tempName = rawFileDirName + tempName;
335 }
336 #ifdef __WINNT__
337 if (!PathCanonicalizeA(tmpPath, (resourcesIndexPath + "/resources/" + tempName).c_str())) {
338 continue;
339 }
340 #else
341 if (realpath((resourcesIndexPath + "/resources/" + tempName).c_str(), tmpPath) == nullptr) {
342 RESMGR_HILOGE(RESMGR_TAG, "FindRawFile path to realpath error");
343 continue;
344 }
345 #endif
346 const std::string realPath = tmpPath;
347 std::fstream inputFile;
348 inputFile.open(realPath, std::ios::in);
349 if (inputFile) {
350 outValue = realPath;
351 inputFile.close();
352 return SUCCESS;
353 }
354 }
355 return ERROR_CODE_RES_PATH_INVALID;
356 }
357
UpdateResConfig(ResConfig & resConfig)358 RState HapManager::UpdateResConfig(ResConfig &resConfig)
359 {
360 WriteLock lock(this->mutex_);
361 bool needUpdate = !this->resConfig_->MatchLocal(resConfig);
362 this->resConfig_->Copy(resConfig);
363 if (needUpdate) {
364 for (auto &resource : hapResources_) {
365 RState state = resource->Update(this->resConfig_);
366 if (state != SUCCESS) {
367 return state;
368 }
369 }
370 }
371 return SUCCESS;
372 }
373
UpdateOverrideResConfig(ResConfig & resConfig)374 RState HapManager::UpdateOverrideResConfig(ResConfig &resConfig)
375 {
376 WriteLock lock(this->mutex_);
377 bool needUpdate = !this->overrideResConfig_->MatchLocal(resConfig);
378 this->overrideResConfig_->Copy(resConfig);
379 if (needUpdate) {
380 for (auto &resource : hapResources_) {
381 RState state = resource->Update(this->overrideResConfig_);
382 if (state != SUCCESS) {
383 return state;
384 }
385 }
386 }
387 return SUCCESS;
388 }
389
GetResConfig(ResConfig & resConfig)390 void HapManager::GetResConfig(ResConfig &resConfig)
391 {
392 ReadLock lock(this->mutex_);
393 resConfig.Copy(*(this->resConfig_), true);
394 }
395
GetResConfigById(uint32_t resId,ResConfig & resConfig,bool isGetOverrideResource,uint32_t density)396 RState HapManager::GetResConfigById(uint32_t resId, ResConfig &resConfig, bool isGetOverrideResource, uint32_t density)
397 {
398 auto qualifierValue = FindQualifierValueById(resId, isGetOverrideResource, density);
399 if (qualifierValue == nullptr) {
400 return ERROR_CODE_RES_NOT_FOUND_BY_ID;
401 }
402 resConfig.Copy(*(qualifierValue->GetResConfig()), true);
403 return SUCCESS;
404 }
405
GetResConfigByName(const std::string & name,const ResType type,ResConfig & resConfig,bool isGetOverrideResource,uint32_t density)406 RState HapManager::GetResConfigByName(const std::string &name, const ResType type, ResConfig &resConfig,
407 bool isGetOverrideResource, uint32_t density)
408 {
409 auto qualifierValue = FindQualifierValueByName(name.c_str(), type, isGetOverrideResource, density);
410 if (qualifierValue == nullptr) {
411 return ERROR_CODE_RES_NOT_FOUND_BY_NAME;
412 }
413 resConfig.Copy(*(qualifierValue->GetResConfig()), true);
414 return SUCCESS;
415 }
416
GetOverrideResConfig(ResConfig & resConfig)417 void HapManager::GetOverrideResConfig(ResConfig &resConfig)
418 {
419 ReadLock lock(this->mutex_);
420 resConfig.Copy(*(this->overrideResConfig_));
421 }
422
AddResource(const char * path,const uint32_t & selectedTypes,bool forceReload)423 bool HapManager::AddResource(const char *path, const uint32_t &selectedTypes, bool forceReload)
424 {
425 WriteLock lock(this->mutex_);
426 std::string sPath(path);
427 #if defined(__ARKUI_CROSS__)
428 if (forceReload) {
429 HapResourceManager::GetInstance().RemoveHapResource(sPath);
430 RemoveHapResource(sPath);
431 }
432 #endif
433 auto it = loadedHapPaths_.find(sPath);
434 if (it != loadedHapPaths_.end()) {
435 return false;
436 }
437 std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
438 std::shared_ptr<HapResource> pResource =
439 HapResourceManager::GetInstance().Load(path, config, isSystem_, false, selectedTypes);
440 if (pResource == nullptr) {
441 return false;
442 }
443 this->loadedHapPaths_[sPath] = std::vector<std::string>();
444 this->hapResources_.push_back(pResource);
445 if (pResource->HasDarkRes()) {
446 this->resConfig_->SetAppDarkRes(true);
447 }
448 if (!pResource->IsSystemResource() && !pResource->IsOverlayResource()
449 && pResource->IsThemeSystemResEnable()) {
450 this->isThemeSystemResEnable_ = true;
451 }
452 return true;
453 }
454
AddPatchResource(const char * path,const char * patchPath)455 bool HapManager::AddPatchResource(const char *path, const char *patchPath)
456 {
457 WriteLock lock(this->mutex_);
458 std::string sPath(path);
459 auto it = loadedHapPaths_.find(sPath);
460 if (it == loadedHapPaths_.end()) {
461 RESMGR_HILOGW(RESMGR_TAG, "AddPatchResource hapPath not load");
462 return false;
463 }
464 std::string sPatchPath(patchPath);
465 return HapResourceManager::GetInstance().PutPatchResource(sPath, sPatchPath);
466 }
467
AddResource(const std::string & path,const std::vector<std::string> & overlayPaths)468 bool HapManager::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
469 {
470 WriteLock lock(this->mutex_);
471 std::vector<std::string> targetOverlay = loadedHapPaths_[path];
472 if (!targetOverlay.empty() && targetOverlay == overlayPaths) {
473 RESMGR_HILOGI(RESMGR_TAG, "the overlay hap already been loaded");
474 return true;
475 }
476 std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
477 std::unordered_map<std::string, std::shared_ptr<HapResource>> result =
478 HapResourceManager::GetInstance().LoadOverlays(path, overlayPaths, config, isSystem_);
479 if (result.size() == 0) {
480 return false;
481 }
482 if (result.find(path) != result.end()) {
483 hapResources_.push_back(result[path]);
484 if (result[path]->HasDarkRes()) {
485 this->resConfig_->SetAppDarkRes(true);
486 }
487 if (!result[path]->IsSystemResource() && !result[path]->IsOverlayResource()
488 && result[path]->IsThemeSystemResEnable()) {
489 this->isThemeSystemResEnable_ = true;
490 }
491 }
492 for (auto iter = overlayPaths.rbegin(); iter != overlayPaths.rend(); iter++) {
493 if (result.find(*iter) != result.end()) {
494 hapResources_.push_back(result[*iter]);
495 }
496 }
497 loadedHapPaths_[path] = overlayPaths;
498 return true;
499 }
500
GetValidAppPath()501 std::string HapManager::GetValidAppPath()
502 {
503 std::string appPath;
504 ReadLock lock(this->mutex_);
505 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
506 const std::string tempPath = (*iter)->GetIndexPath();
507 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
508 continue;
509 }
510 appPath = tempPath;
511 }
512 return appPath;
513 }
514
AddAppOverlay(const std::string & overlayPath)515 bool HapManager::AddAppOverlay(const std::string &overlayPath)
516 {
517 char outPath[PATH_MAX + 1] = {0};
518 Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
519 if (outPath[0] == '\0') {
520 RESMGR_HILOGE(RESMGR_TAG, "AddAppOverlay invalid overlayPath");
521 return false;
522 }
523 std::vector<std::string> overlayPaths;
524 overlayPaths.emplace_back(outPath);
525 std::string appPath = GetValidAppPath();
526 return AddResource(appPath, overlayPaths);
527 }
528
RemoveAppOverlay(const std::string & overlayPath)529 bool HapManager::RemoveAppOverlay(const std::string &overlayPath)
530 {
531 char outPath[PATH_MAX + 1] = {0};
532 Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
533 if (outPath[0] == '\0') {
534 RESMGR_HILOGE(RESMGR_TAG, "RemoveAppOverlay invalid overlayPath");
535 return false;
536 }
537 std::vector<std::string> overlayPaths;
538 overlayPaths.emplace_back(outPath);
539 std::string appPath = GetValidAppPath();
540 return RemoveResource(appPath, overlayPaths);
541 }
542
~HapManager()543 HapManager::~HapManager()
544 {
545 #ifndef SUPPORT_ASAN
546 WriteLock lock(this->mutex_);
547 hapResources_.clear();
548 loadedHapPaths_.clear();
549 #endif
550
551 #ifdef SUPPORT_GRAPHICS
552 auto iter = plurRulesCache_.begin();
553 for (; iter != plurRulesCache_.end(); iter++) {
554 RESMGR_HILOGD(RESMGR_TAG, "delete plurRulesMap_ %s", iter->first.c_str());
555 if (iter->second != nullptr) {
556 auto ptr = iter->second;
557 delete (ptr);
558 iter->second = nullptr;
559 }
560 }
561 #endif
562 }
563
GetResourceList(uint32_t ident) const564 std::vector<std::shared_ptr<IdValues>> HapManager::GetResourceList(uint32_t ident) const
565 {
566 std::vector<std::shared_ptr<IdValues>> result;
567 // one id only exit in one hap
568 for (size_t i = 0; i < hapResources_.size(); ++i) {
569 std::shared_ptr<HapResource> pResource = hapResources_[i];
570 const std::shared_ptr<IdValues> out = pResource->GetIdValues(ident);
571 if (out != nullptr) {
572 result.emplace_back(out);
573 }
574 }
575 return result;
576 }
577
GetResourceListByName(const char * name,const ResType resType) const578 std::vector<std::shared_ptr<IdValues>> HapManager::GetResourceListByName(const char *name,
579 const ResType resType) const
580 {
581 std::vector<std::shared_ptr<IdValues>> result;
582 // all match will return
583 if (name == nullptr) {
584 return result;
585 }
586 std::string key(name);
587 for (size_t i = 0; i < hapResources_.size(); ++i) {
588 std::shared_ptr<HapResource> pResource = hapResources_[i];
589 const std::shared_ptr<IdValues> out = pResource->GetIdValuesByName(key, resType);
590 if (out != nullptr) {
591 result.emplace_back(out);
592 }
593 }
594 return result;
595 }
596
597 #if defined(__ARKUI_CROSS__)
RemoveHapResource(const std::string & path)598 void HapManager::RemoveHapResource(const std::string &path)
599 {
600 for (auto iter = hapResources_.begin(); iter != hapResources_.end();) {
601 if ((*iter)->GetIndexPath() == path) {
602 iter = hapResources_.erase(iter);
603 break;
604 } else {
605 ++iter;
606 }
607 }
608
609 auto it = loadedHapPaths_.find(path);
610 if (it != loadedHapPaths_.end()) {
611 loadedHapPaths_.erase(it);
612 }
613 }
614 #endif
615
GetResourcePaths()616 std::vector<std::string> HapManager::GetResourcePaths()
617 {
618 std::vector<std::string> result;
619 ReadLock lock(this->mutex_);
620 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
621 std::string indexPath = (*iter)->GetIndexPath();
622 auto index = indexPath.rfind('/');
623 if (index == std::string::npos) {
624 RESMGR_HILOGE(RESMGR_TAG, "index path format error");
625 continue;
626 }
627
628 result.emplace_back(indexPath.substr(0, index) + "/resources/");
629 }
630
631 return result;
632 }
633
GetImageType(const std::string fileName)634 std::string GetImageType(const std::string fileName)
635 {
636 auto pos = fileName.find_last_of('.');
637 std::string imgType;
638 if (pos != std::string::npos) {
639 imgType = fileName.substr(pos + 1);
640 }
641 return imgType;
642 }
643
644 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> & extractor,const std::shared_ptr<ValueUnderQualifierDir> qd,const ResType resType)645 std::string GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> &extractor,
646 const std::shared_ptr<ValueUnderQualifierDir> qd, const ResType resType)
647 {
648 std::string filePath;
649 if (qd == nullptr) {
650 RESMGR_HILOGE(RESMGR_TAG, "GetFilePathFromHap qd is null");
651 return filePath;
652 }
653 const std::shared_ptr<IdItem> idItem = qd->GetIdItem();
654 if (idItem == nullptr || idItem->resType_ != resType) {
655 std::string hapPath = qd->GetIndexPath();
656 RESMGR_HILOGE(RESMGR_TAG, "actual resType = %{public}d, expect resType = %{public}d",
657 idItem == nullptr ? -1 : idItem->resType_, resType);
658 return filePath;
659 }
660 if (extractor->IsStageModel()) {
661 std::string tempFilePath(idItem->value_);
662 auto index = tempFilePath.find('/');
663 if (index == std::string::npos) {
664 RESMGR_HILOGE(RESMGR_TAG, "resource path format error");
665 return filePath;
666 }
667 filePath = idItem->value_.substr(index + 1);
668 } else {
669 // FA mode
670 std::string tempFilePath("assets/");
671 tempFilePath.append(idItem->value_);
672 filePath = tempFilePath;
673 }
674 return filePath;
675 }
676 #endif
677
678 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetAbilityExtractor(const std::shared_ptr<ValueUnderQualifierDir> qd)679 std::shared_ptr<AbilityBase::Extractor> GetAbilityExtractor(
680 const std::shared_ptr<ValueUnderQualifierDir> qd)
681 {
682 std::string hapPath = qd->GetIndexPath();
683 bool isNewExtractor = false;
684 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
685 return extractor;
686 }
687 #endif
688
GetProfileData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)689 RState HapManager::GetProfileData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
690 std::unique_ptr<uint8_t[]> &outValue)
691 {
692 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
693 auto extractor = GetAbilityExtractor(qualifierDir);
694 if (extractor == nullptr) {
695 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
696 return NOT_FOUND;
697 }
698 std::string filePath = GetFilePathFromHap(extractor, qualifierDir, ResType::PROF);
699 if (filePath.empty()) {
700 RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetProfileData");
701 return NOT_FOUND;
702 }
703 bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
704 if (!ret) {
705 RESMGR_HILOGE(RESMGR_TAG, "failed to get config data from ability");
706 return NOT_FOUND;
707 }
708 #endif
709 return SUCCESS;
710 }
711
GetMediaData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)712 RState HapManager::GetMediaData(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
713 std::unique_ptr<uint8_t[]> &outValue)
714 {
715 std::string filePath = qualifierDir->GetIndexPath();
716 RState state;
717 if (Utils::ContainsTail(filePath, Utils::tailSet)) {
718 state = HapManager::GetMediaDataFromHap(qualifierDir, len, outValue);
719 } else {
720 state = HapManager::GetMediaDataFromIndex(qualifierDir, len, outValue);
721 }
722 return state;
723 }
724
GetMediaDataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)725 RState HapManager::GetMediaDataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
726 std::unique_ptr<uint8_t[]> &outValue)
727 {
728 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
729 HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
730 auto extractor = GetAbilityExtractor(qualifierDir);
731 if (extractor == nullptr) {
732 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
733 return NOT_FOUND;
734 }
735 std::string filePath = GetFilePathFromHap(extractor, qualifierDir, ResType::MEDIA);
736 if (filePath.empty()) {
737 RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetMediaDataFromHap");
738 return NOT_FOUND;
739 }
740 bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
741 if (!ret) {
742 RESMGR_HILOGE(RESMGR_TAG, "failed to get media data from ability");
743 return NOT_FOUND;
744 }
745 #endif
746 return SUCCESS;
747 }
748
GetMediaDataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,size_t & len,std::unique_ptr<uint8_t[]> & outValue)749 RState HapManager::GetMediaDataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, size_t &len,
750 std::unique_ptr<uint8_t[]> &outValue)
751 {
752 std::string filePath;
753 RState state = HapManager::GetFilePath(qualifierDir, ResType::MEDIA, filePath);
754 if (state != SUCCESS) {
755 return NOT_FOUND;
756 }
757 outValue = Utils::LoadResourceFile(filePath, len);
758 return SUCCESS;
759 }
760
GetMediaBase64Data(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,std::string & outValue)761 RState HapManager::GetMediaBase64Data(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,
762 std::string &outValue)
763 {
764 std::string filePath = qualifierDir->GetIndexPath();
765 RState state;
766 if (Utils::ContainsTail(filePath, Utils::tailSet)) {
767 state = HapManager::GetMediaBase64DataFromHap(qualifierDir, outValue);
768 } else {
769 state = HapManager::GetMediaBase64DataFromIndex(qualifierDir, outValue);
770 }
771 return state;
772 }
773
GetMediaBase64DataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,std::string & outValue)774 RState HapManager::GetMediaBase64DataFromHap(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,
775 std::string &outValue)
776 {
777 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
778 auto extractor = GetAbilityExtractor(qualifierDir);
779 if (extractor == nullptr) {
780 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
781 return NOT_FOUND;
782 }
783 std::string filePath = GetFilePathFromHap(extractor, qualifierDir, ResType::MEDIA);
784 std::unique_ptr<uint8_t[]> buffer;
785 size_t tmpLen;
786 bool ret = extractor->ExtractToBufByName(filePath, buffer, tmpLen);
787 if (!ret) {
788 RESMGR_HILOGE(RESMGR_TAG, "failed to get mediabase64 data from ability");
789 return NOT_FOUND;
790 }
791 std::string imgType = GetImageType(filePath);
792 Utils::EncodeBase64(buffer, tmpLen, imgType, outValue);
793 #endif
794 return SUCCESS;
795 }
796
GetMediaBase64DataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,std::string & outValue)797 RState HapManager::GetMediaBase64DataFromIndex(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,
798 std::string &outValue)
799 {
800 std::string filePath;
801 RState state = HapManager::GetFilePath(qualifierDir, ResType::MEDIA, filePath);
802 if (state != SUCCESS) {
803 return NOT_FOUND;
804 }
805 return Utils::GetMediaBase64Data(filePath, outValue);
806 }
807
GetValidHapPath(std::string & hapPath)808 int32_t HapManager::GetValidHapPath(std::string &hapPath)
809 {
810 ReadLock lock(this->mutex_);
811 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
812 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
813 continue;
814 }
815 const std::string tempPath = (*iter)->GetIndexPath();
816 if (Utils::ContainsTail(tempPath, Utils::tailSet)) {
817 hapPath = tempPath;
818 return OK;
819 }
820 }
821 return NOT_FOUND;
822 }
823
GetValidResourceIndexPath(std::string & indexPath)824 int32_t HapManager::GetValidResourceIndexPath(std::string &indexPath)
825 {
826 ReadLock lock(this->mutex_);
827 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
828 const std::string tempPath = (*iter)->GetIndexPath();
829 if (Utils::IsSystemPath(tempPath)) {
830 continue;
831 }
832 indexPath = tempPath;
833 return OK;
834 }
835 return NOT_FOUND;
836 }
837
FindRawFileFromHap(const std::string & rawFileName,size_t & len,std::unique_ptr<uint8_t[]> & outValue)838 RState HapManager::FindRawFileFromHap(const std::string &rawFileName, size_t &len,
839 std::unique_ptr<uint8_t[]> &outValue)
840 {
841 ReadLock lock(this->mutex_);
842 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
843 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
844 continue;
845 }
846 std::string tempPath = (*iter)->GetIndexPath();
847 std::string tempPatchPath;
848 if ((*iter)->HasPatch()) {
849 tempPatchPath = (*iter)->GetPatchPath();
850 }
851 if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
852 RState state = HapParser::ReadRawFileFromHap(tempPath, tempPatchPath, rawFileName, len, outValue);
853 if (state != SUCCESS) {
854 continue;
855 }
856 } else { // if file path is uncompressed
857 std::string filePath;
858 HapManager::FindRawFile(rawFileName, filePath);
859 outValue = Utils::LoadResourceFile(filePath, len);
860 if (outValue == nullptr) {
861 continue;
862 }
863 }
864 return SUCCESS;
865 }
866 return ERROR_CODE_RES_PATH_INVALID;
867 }
868
FindRawFileDescriptorFromHap(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)869 RState HapManager::FindRawFileDescriptorFromHap(const std::string &rawFileName,
870 ResourceManager::RawFileDescriptor &descriptor)
871 {
872 std::lock_guard<std::mutex> lock(g_rawFileLock);
873 auto it = rawFileDescriptor_.find(rawFileName);
874 if (it != rawFileDescriptor_.end()) {
875 descriptor.fd = rawFileDescriptor_[rawFileName].fd;
876 descriptor.length = rawFileDescriptor_[rawFileName].length;
877 descriptor.offset = rawFileDescriptor_[rawFileName].offset;
878 return SUCCESS;
879 }
880 RState state = GetRawFd(rawFileName, descriptor);
881 if (state == SUCCESS) {
882 rawFileDescriptor_[rawFileName] = descriptor;
883 }
884 return state;
885 }
886
GetRawFd(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)887 RState HapManager::GetRawFd(const std::string &rawFileName, ResourceManager::RawFileDescriptor &descriptor)
888 {
889 RState state;
890 ReadLock lock(this->mutex_);
891 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
892 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
893 continue;
894 }
895 std::string tempPath = (*iter)->GetIndexPath();
896 std::string tempPatchPath;
897 if ((*iter)->HasPatch()) {
898 tempPatchPath = (*iter)->GetPatchPath();
899 }
900 if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
901 state = HapParser::ReadRawFileDescriptor(tempPath.c_str(), tempPatchPath.c_str(), rawFileName, descriptor);
902 } else { // if file path is uncompressed
903 state = HapManager::FindRawFileDescriptor(rawFileName, descriptor);
904 }
905 if (state != SUCCESS) {
906 continue;
907 }
908 return SUCCESS;
909 }
910 return ERROR_CODE_RES_PATH_INVALID;
911 }
912
GetRawFileList(const std::string & rawDirPath,std::vector<std::string> & fileList)913 RState HapManager::GetRawFileList(const std::string &rawDirPath, std::vector<std::string> &fileList)
914 {
915 std::string hapOrIndexPath;
916 if (HapManager::GetValidHapPath(hapOrIndexPath) == OK) {
917 std::string temPatchPath;
918 {
919 ReadLock lock(this->mutex_);
920 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
921 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
922 continue;
923 }
924 if ((*iter)->GetIndexPath() == hapOrIndexPath && (*iter)->HasPatch()) {
925 temPatchPath = (*iter)->GetPatchPath();
926 }
927 }
928 }
929 std::set<std::string> fileSet;
930 RState hapState = HapParser::GetRawFileList(hapOrIndexPath, rawDirPath, fileSet);
931 RState hqfState = NOT_FOUND;
932 if (!temPatchPath.empty()) {
933 hqfState = HapParser::GetRawFileList(temPatchPath, rawDirPath, fileSet);
934 }
935 for (auto it = fileSet.begin(); it != fileSet.end(); it++) {
936 fileList.emplace_back(*it);
937 }
938 return (hapState != SUCCESS && hqfState != SUCCESS) ? ERROR_CODE_RES_PATH_INVALID : SUCCESS;
939 }
940 if (HapManager::GetValidResourceIndexPath(hapOrIndexPath) == OK) {
941 return HapParser::GetRawFileListUnCompressed(hapOrIndexPath, rawDirPath, fileList);
942 }
943 return ERROR_CODE_RES_PATH_INVALID;
944 }
945
IsLoadHap(std::string & hapPath)946 bool HapManager::IsLoadHap(std::string &hapPath)
947 {
948 return HapManager::GetValidHapPath(hapPath) == OK ? true : false;
949 }
950
GetFilePath(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir,const ResType resType,std::string & outValue)951 RState HapManager::GetFilePath(const std::shared_ptr<ValueUnderQualifierDir> qualifierDir, const ResType resType,
952 std::string &outValue)
953 {
954 // not found or type invalid
955 if (qualifierDir == nullptr) {
956 return NOT_FOUND;
957 }
958 const std::shared_ptr<IdItem> idItem = qualifierDir->GetIdItem();
959 if (idItem == nullptr || idItem->resType_ != resType) {
960 return NOT_FOUND;
961 }
962 outValue = qualifierDir->GetResourcePath();
963 #if defined(__ARKUI_CROSS__)
964 auto index = idItem->value_.find('/');
965 if (index == std::string::npos) {
966 RESMGR_HILOGE(RESMGR_TAG, "resource path format error");
967 return NOT_FOUND;
968 }
969 auto nameWithoutModule = idItem->value_.substr(index + 1);
970 outValue.append(nameWithoutModule);
971 #elif defined(__IDE_PREVIEW__)
972 if (Utils::IsFileExist(idItem->value_)) {
973 outValue = idItem->value_;
974 return SUCCESS;
975 }
976 auto index = idItem->value_.find('/');
977 if (index == std::string::npos) {
978 RESMGR_HILOGE(RESMGR_TAG, "resource path format error");
979 return NOT_FOUND;
980 }
981 auto nameWithoutModule = idItem->value_.substr(index + 1);
982 outValue.append(nameWithoutModule);
983 #else
984 outValue.append(idItem->value_);
985 #endif
986 return SUCCESS;
987 }
988
FindRawFileDescriptor(const std::string & name,ResourceManager::RawFileDescriptor & descriptor)989 RState HapManager::FindRawFileDescriptor(const std::string &name, ResourceManager::RawFileDescriptor &descriptor)
990 {
991 std::string paths = "";
992 RState rState = HapManager::FindRawFile(name, paths);
993 if (rState != SUCCESS) {
994 return rState;
995 }
996 char outPath[PATH_MAX + 1] = {0};
997 Utils::CanonicalizePath(paths.c_str(), outPath, PATH_MAX);
998 int fd = open(outPath, O_RDONLY);
999 if (fd > 0) {
1000 long length = lseek(fd, 0, SEEK_END);
1001 if (length == -1) {
1002 close(fd);
1003 return ERROR_CODE_RES_PATH_INVALID;
1004 }
1005 long begin = lseek(fd, 0, SEEK_SET);
1006 if (begin == -1) {
1007 close(fd);
1008 return ERROR_CODE_RES_PATH_INVALID;
1009 }
1010 descriptor.fd = fd;
1011 descriptor.length = length;
1012 descriptor.offset = 0;
1013 return SUCCESS;
1014 }
1015 return ERROR_CODE_RES_PATH_INVALID;
1016 }
1017
CloseRawFileDescriptor(const std::string & name)1018 RState HapManager::CloseRawFileDescriptor(const std::string &name)
1019 {
1020 std::lock_guard<std::mutex> lock(g_rawFileLock);
1021 auto it = rawFileDescriptor_.find(name);
1022 if (it == rawFileDescriptor_.end()) {
1023 return ERROR_CODE_RES_PATH_INVALID;
1024 }
1025
1026 int fd = rawFileDescriptor_[name].fd;
1027 if (fd <= 0) {
1028 return ERROR_CODE_RES_PATH_INVALID;
1029 }
1030
1031 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
1032 if (fdsan_get_owner_tag(fd) != 0) {
1033 rawFileDescriptor_.erase(name);
1034 return SUCCESS;
1035 }
1036 #endif
1037
1038 if (close(fd) == -1) {
1039 return ERROR_CODE_RES_PATH_INVALID;
1040 }
1041
1042 rawFileDescriptor_.erase(name);
1043 return SUCCESS;
1044 }
1045
RemoveResource(const std::string & path,const std::vector<std::string> & overlayPaths)1046 bool HapManager::RemoveResource(const std::string &path, const std::vector<std::string> &overlayPaths)
1047 {
1048 WriteLock lock(this->mutex_);
1049 if (loadedHapPaths_.find(path) == loadedHapPaths_.end()) {
1050 return false;
1051 }
1052 std::vector<std::string> targetOverlay = loadedHapPaths_[path];
1053 if (targetOverlay.empty()) {
1054 RESMGR_HILOGE(RESMGR_TAG, "the hap have not overlay");
1055 return false;
1056 }
1057 char outPath[PATH_MAX] = {0};
1058 for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
1059 Utils::CanonicalizePath((*iter).c_str(), outPath, PATH_MAX);
1060 if (outPath[0] == '\0') {
1061 RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath");
1062 continue;
1063 }
1064 if (std::find(targetOverlay.begin(), targetOverlay.end(), outPath) != targetOverlay.end()) {
1065 targetOverlay.erase(std::remove(targetOverlay.begin(), targetOverlay.end(), outPath),
1066 targetOverlay.end());
1067 }
1068 for (auto resIter = hapResources_.begin(); resIter != hapResources_.end();) {
1069 if ((*resIter) == nullptr) {
1070 RESMGR_HILOGE(RESMGR_TAG, "hapResource is nullptr");
1071 return false;
1072 }
1073 std::string hapPath = (*resIter)->GetIndexPath();
1074 if (hapPath == outPath) {
1075 resIter = hapResources_.erase(resIter);
1076 } else {
1077 resIter++;
1078 }
1079 }
1080 }
1081 loadedHapPaths_[path] = targetOverlay;
1082 return true;
1083 }
1084
GetHapResource()1085 std::vector<std::shared_ptr<HapResource>> HapManager::GetHapResource()
1086 {
1087 return hapResources_;
1088 }
1089
AddSystemResource(const std::shared_ptr<HapManager> & systemHapManager)1090 void HapManager::AddSystemResource(const std::shared_ptr<HapManager> &systemHapManager)
1091 {
1092 if (systemHapManager == nullptr) {
1093 RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, systemHapManager is nullptr");
1094 return;
1095 }
1096 if (!systemHapManager->isSystem_) {
1097 RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, the added hapManager is not system");
1098 return;
1099 }
1100 WriteLock lock(this->mutex_);
1101 // add system resource to app resource vector
1102 const std::vector<std::shared_ptr<HapResource>> &systemResources = systemHapManager->hapResources_;
1103 for (size_t i = 0; i < systemResources.size(); i++) {
1104 this->hapResources_.push_back(systemResources[i]);
1105 }
1106
1107 // add system loaded path to app loaded path map.
1108 const std::unordered_map<std::string, std::vector<std::string>> &loadedSystemPaths =
1109 systemHapManager->loadedHapPaths_;
1110 for (auto iter = loadedSystemPaths.begin(); iter != loadedSystemPaths.end(); iter++) {
1111 const std::vector<std::string> &overlayPaths = iter->second;
1112 if (this->loadedHapPaths_.find(iter->first) == this->loadedHapPaths_.end()) {
1113 this->loadedHapPaths_[iter->first] = overlayPaths;
1114 }
1115 }
1116 }
1117
GetResourceLimitKeys()1118 uint32_t HapManager::GetResourceLimitKeys()
1119 {
1120 ReadLock lock(this->mutex_);
1121 uint32_t limitKeysValue = 0;
1122 for (size_t i = 0; i < hapResources_.size(); i++) {
1123 limitKeysValue |= hapResources_[i]->GetLimitKeysValue();
1124 }
1125 RESMGR_HILOGD(RESMGR_TAG, "hap manager limit key is %{public}u", limitKeysValue);
1126 return limitKeysValue;
1127 }
1128
1129 std::unordered_map<std::string, ResType> ResTypeMap {
1130 {"integer", INTEGER},
1131 {"string", STRING},
1132 {"strarray", STRINGARRAY},
1133 {"intarray", INTARRAY},
1134 {"boolean", BOOLEAN},
1135 {"color", COLOR},
1136 {"theme", THEME},
1137 {"plural", PLURALS},
1138 {"float", FLOAT},
1139 {"media", MEDIA},
1140 {"profile", PROF},
1141 {"pattern", PATTERN},
1142 {"symbol", SYMBOL},
1143 };
1144
IsPrefix(std::string_view prefix,std::string_view full)1145 bool IsPrefix(std::string_view prefix, std::string_view full)
1146 {
1147 return prefix == full.substr(0, prefix.size());
1148 }
1149
GetRealResId(const std::string & resType,const std::vector<std::unordered_map<ResType,uint32_t>> & candidates)1150 uint32_t GetRealResId(const std::string &resType,
1151 const std::vector<std::unordered_map<ResType, uint32_t>> &candidates)
1152 {
1153 for (auto candidate : candidates) {
1154 for (auto data : candidate) {
1155 if (ResTypeMap.find(resType) != ResTypeMap.end() && ResTypeMap[resType] == data.first) {
1156 return data.second;
1157 }
1158 }
1159 }
1160 return 0;
1161 }
1162
GetResTypeAndResName(const std::string & resTypeName)1163 std::tuple<std::string, std::string> GetResTypeAndResName(const std::string &resTypeName)
1164 {
1165 std::tuple<std::string, std::string> typeNameTuple;
1166 auto pos1 = resTypeName.find('.');
1167 auto pos2 = resTypeName.rfind('.');
1168 if (pos1 == std::string::npos || pos2 == std::string::npos) {
1169 return std::make_tuple("", "");
1170 }
1171 if (pos2 < pos1 + 1) {
1172 return std::make_tuple("", "");
1173 }
1174 const std::string resType = resTypeName.substr(pos1 + 1, pos2 - pos1 - 1);
1175 if (ResTypeMap.find(resType) == ResTypeMap.end()) {
1176 return std::make_tuple("", "");
1177 }
1178 const std::string resName = resTypeName.substr(pos2 + 1);
1179 if (resName.empty()) {
1180 return std::make_tuple("", "");
1181 }
1182 typeNameTuple = std::make_tuple(resType, resName);
1183 return typeNameTuple;
1184 }
1185
GetResId(const std::string & resTypeName,uint32_t & resId)1186 RState HapManager::GetResId(const std::string &resTypeName, uint32_t &resId)
1187 {
1188 auto typeNameTuple = GetResTypeAndResName(resTypeName);
1189 const std::string resType = std::get<0>(typeNameTuple);
1190 const std::string resName = std::get<1>(typeNameTuple);
1191 if (resType.empty() || resName.empty()) {
1192 RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1193 return NOT_FOUND;
1194 }
1195 bool isSystem = IsPrefix("sys", resTypeName);
1196 bool isApp = IsPrefix("app", resTypeName);
1197 if (!isSystem && !isApp) {
1198 RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1199 return NOT_FOUND;
1200 }
1201 ReadLock lock(this->mutex_);
1202 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1203 bool isSystemResource = (*iter)->IsSystemResource();
1204 bool isOverlayResource = (*iter)->IsOverlayResource();
1205 if (isOverlayResource) {
1206 continue;
1207 }
1208 if (isSystem && !isSystemResource) {
1209 continue;
1210 }
1211 if (isApp && isSystemResource) {
1212 continue;
1213 }
1214 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> nameTypeIdMap =
1215 (*iter)->BuildNameTypeIdMapping();
1216 std::vector<std::unordered_map<ResType, uint32_t>> candidates;
1217 for (auto data : nameTypeIdMap) {
1218 if (data.first != resName) {
1219 continue;
1220 }
1221 candidates.emplace_back(data.second);
1222 }
1223 resId = GetRealResId(resType, candidates);
1224 if (resId != 0) {
1225 return SUCCESS;
1226 }
1227 }
1228 if (resId == 0) {
1229 RESMGR_HILOGE(RESMGR_TAG, "GetResId name:%{public}s, resType:%{public}s", resName.c_str(), resType.c_str());
1230 }
1231 return NOT_FOUND;
1232 }
1233
GetLocales(std::vector<std::string> & outValue,bool includeSystem)1234 void HapManager::GetLocales(std::vector<std::string> &outValue, bool includeSystem)
1235 {
1236 if (isSystem_) {
1237 includeSystem = true;
1238 }
1239 std::set<std::string> result;
1240 ReadLock lock(this->mutex_);
1241 for (size_t i = 0; i < hapResources_.size(); i++) {
1242 hapResources_[i]->GetLocales(result, includeSystem);
1243 }
1244 outValue.assign(result.begin(), result.end());
1245 }
1246
IsRawDirFromHap(const std::string & pathName,bool & outValue)1247 RState HapManager::IsRawDirFromHap(const std::string &pathName, bool &outValue)
1248 {
1249 ReadLock lock(this->mutex_);
1250 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1251 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
1252 continue;
1253 }
1254 const std::string tempPath = (*iter)->GetIndexPath();
1255 if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
1256 RState state = HapParser::IsRawDirFromHap(tempPath.c_str(), pathName, outValue);
1257 if (state != SUCCESS) {
1258 continue;
1259 }
1260 } else { // if file path is uncompressed
1261 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
1262 RState state = HapParser::IsRawDirUnCompressed(pathName, outValue);
1263 if (state != SUCCESS) {
1264 continue;
1265 }
1266 #else
1267 const std::string finalPath = (*iter)->GetResourcePath() + RAW_FILE_PATH + pathName;
1268 RState state = HapParser::IsRawDirUnCompressed(finalPath, outValue);
1269 if (state != SUCCESS) {
1270 continue;
1271 }
1272 #endif
1273 }
1274 return SUCCESS;
1275 }
1276 return ERROR_CODE_RES_PATH_INVALID;
1277 }
1278
IsThemeSystemResEnableHap()1279 bool HapManager::IsThemeSystemResEnableHap()
1280 {
1281 ReadLock lock(this->mutex_);
1282 return this->isThemeSystemResEnable_;
1283 }
1284
IsSystem()1285 bool HapManager::IsSystem()
1286 {
1287 return this->isSystem_;
1288 }
1289
GetLoadedHapPaths()1290 std::unordered_map<std::string, std::vector<std::string>> HapManager::GetLoadedHapPaths()
1291 {
1292 return this->loadedHapPaths_;
1293 }
1294
UpdateAppConfigForSysResManager(bool isAppDarkRes,bool isThemeSystemResEnable)1295 void HapManager::UpdateAppConfigForSysResManager(bool isAppDarkRes, bool isThemeSystemResEnable)
1296 {
1297 WriteLock lock(this->mutex_);
1298 if (this->isSystem_ && this->isUpdateAppConfig_) {
1299 this->isUpdateAppConfig_ = false;
1300 this->resConfig_->SetAppDarkRes(isAppDarkRes);
1301 this->isThemeSystemResEnable_ = isThemeSystemResEnable;
1302 }
1303 }
1304 } // namespace Resource
1305 } // namespace Global
1306 } // namespace OHOS
1307