1 /*
2 * Copyright (c) 2021-2024 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__)
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<HapResource::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<HapResource::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<HapResource::ValueUnderQualifierDir> HapManager::FindQualifierValueById(uint32_t id,
203 bool isGetOverrideResource, uint32_t density)
204 {
205 ReadLock lock(this->mutex_);
206 std::vector<std::shared_ptr<HapResource::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<HapResource::ValueUnderQualifierDir> & result,const std::vector<std::shared_ptr<HapResource::ValueUnderQualifierDir>> & paths,uint32_t density,std::shared_ptr<ResConfigImpl> currentResConfig)259 void HapManager::MatchBestResource(std::shared_ptr<ResConfigImpl> &bestResConfig,
260 std::shared_ptr<HapResource::ValueUnderQualifierDir> &result,
261 const std::vector<std::shared_ptr<HapResource::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<HapResource::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<HapResource::IdValues>> & candidates,uint32_t density,bool isGetOverrideResource)284 const std::shared_ptr<HapResource::ValueUnderQualifierDir> HapManager::GetBestMatchResource(
285 const std::vector<std::shared_ptr<HapResource::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<HapResource::ValueUnderQualifierDir> result = nullptr;
290 std::shared_ptr<HapResource::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]->IsOverlay();
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, %s", indexPath.c_str());
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->UpdateResConfig(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->UpdateResConfig(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 return this->AddResourcePath(path, selectedTypes, forceReload);
427 }
428
AddPatchResource(const char * path,const char * patchPath)429 bool HapManager::AddPatchResource(const char *path, const char *patchPath)
430 {
431 WriteLock lock(this->mutex_);
432 return this->AddPatchResourcePath(path, patchPath);
433 }
434
AddResource(const std::string & path,const std::vector<std::string> & overlayPaths)435 bool HapManager::AddResource(const std::string &path, const std::vector<std::string> &overlayPaths)
436 {
437 WriteLock lock(this->mutex_);
438 std::vector<std::string> targetOverlay = loadedHapPaths_[path];
439 if (!targetOverlay.empty() && targetOverlay == overlayPaths) {
440 RESMGR_HILOGI(RESMGR_TAG, "the overlay for %{public}s already been loaded", path.c_str());
441 return true;
442 }
443 std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
444 std::unordered_map<std::string, std::shared_ptr<HapResource>> result = HapResource::LoadOverlays(path, overlayPaths,
445 config, isSystem_);
446 if (result.size() == 0) {
447 return false;
448 }
449 if (result.find(path) != result.end()) {
450 hapResources_.push_back(result[path]);
451 if (result[path]->HasDarkRes()) {
452 this->resConfig_->SetAppDarkRes(true);
453 }
454 }
455 for (auto iter = overlayPaths.rbegin(); iter != overlayPaths.rend(); iter++) {
456 if (result.find(*iter) != result.end()) {
457 hapResources_.push_back(result[*iter]);
458 }
459 }
460 loadedHapPaths_[path] = overlayPaths;
461 return true;
462 }
463
GetValidAppPath()464 std::string HapManager::GetValidAppPath()
465 {
466 std::string appPath;
467 ReadLock lock(this->mutex_);
468 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
469 const std::string tempPath = (*iter)->GetIndexPath();
470 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
471 continue;
472 }
473 appPath = tempPath;
474 }
475 return appPath;
476 }
477
AddAppOverlay(const std::string & overlayPath)478 bool HapManager::AddAppOverlay(const std::string &overlayPath)
479 {
480 RESMGR_HILOGI(RESMGR_TAG, "AddAppOverlay overlayPath = %{public}s", overlayPath.c_str());
481 char outPath[PATH_MAX + 1] = {0};
482 Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
483 if (outPath[0] == '\0') {
484 RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath, %{public}s", overlayPath.c_str());
485 return false;
486 }
487 std::vector<std::string> overlayPaths;
488 overlayPaths.emplace_back(outPath);
489 std::string appPath = GetValidAppPath();
490 return AddResource(appPath, overlayPaths);
491 }
492
RemoveAppOverlay(const std::string & overlayPath)493 bool HapManager::RemoveAppOverlay(const std::string &overlayPath)
494 {
495 RESMGR_HILOGI(RESMGR_TAG, "RemoveAppOverlay overlayPath = %{public}s", overlayPath.c_str());
496 char outPath[PATH_MAX + 1] = {0};
497 Utils::CanonicalizePath(overlayPath.c_str(), outPath, PATH_MAX);
498 if (outPath[0] == '\0') {
499 RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath, %{public}s", overlayPath.c_str());
500 return false;
501 }
502 std::vector<std::string> overlayPaths;
503 overlayPaths.emplace_back(outPath);
504 std::string appPath = GetValidAppPath();
505 return RemoveResource(appPath, overlayPaths);
506 }
507
~HapManager()508 HapManager::~HapManager()
509 {
510 WriteLock lock(this->mutex_);
511 hapResources_.clear();
512 loadedHapPaths_.clear();
513 #ifdef SUPPORT_GRAPHICS
514 auto iter = plurRulesCache_.begin();
515 for (; iter != plurRulesCache_.end(); iter++) {
516 RESMGR_HILOGD(RESMGR_TAG, "delete plurRulesMap_ %s", iter->first.c_str());
517 if (iter->second != nullptr) {
518 auto ptr = iter->second;
519 delete (ptr);
520 iter->second = nullptr;
521 }
522 }
523 #endif
524 }
525
GetResourceList(uint32_t ident) const526 std::vector<std::shared_ptr<HapResource::IdValues>> HapManager::GetResourceList(uint32_t ident) const
527 {
528 std::vector<std::shared_ptr<HapResource::IdValues>> result;
529 // one id only exit in one hap
530 for (size_t i = 0; i < hapResources_.size(); ++i) {
531 std::shared_ptr<HapResource> pResource = hapResources_[i];
532 const std::shared_ptr<HapResource::IdValues>out = pResource->GetIdValues(ident);
533 if (out != nullptr) {
534 result.emplace_back(out);
535 }
536 }
537 return result;
538 }
539
GetResourceListByName(const char * name,const ResType resType) const540 std::vector<std::shared_ptr<HapResource::IdValues>> HapManager::GetResourceListByName(const char *name,
541 const ResType resType) const
542 {
543 std::vector<std::shared_ptr<HapResource::IdValues>> result;
544 // all match will return
545 if (name == nullptr) {
546 return result;
547 }
548 std::string key(name);
549 for (size_t i = 0; i < hapResources_.size(); ++i) {
550 std::shared_ptr<HapResource> pResource = hapResources_[i];
551 const std::shared_ptr<HapResource::IdValues> out = pResource->GetIdValuesByName(key, resType);
552 if (out != nullptr) {
553 result.emplace_back(out);
554 }
555 }
556 return result;
557 }
558
AddResourcePath(const char * path,const uint32_t & selectedTypes,bool forceReload)559 bool HapManager::AddResourcePath(const char *path, const uint32_t &selectedTypes, bool forceReload)
560 {
561 std::string sPath(path);
562 #if defined(__ARKUI_CROSS__)
563 if (forceReload) {
564 HapResourceManager::GetInstance()->RemoveHapResource(sPath);
565 RemoveHapResource(sPath);
566 }
567 #endif
568 auto it = loadedHapPaths_.find(sPath);
569 if (it != loadedHapPaths_.end()) {
570 return false;
571 }
572 std::shared_ptr<ResConfigImpl> config = getCompleteOverrideConfig(isOverride_);
573 std::shared_ptr<HapResource> pResource = HapResource::Load(path, config, isSystem_, false, selectedTypes);
574 if (pResource == nullptr) {
575 return false;
576 }
577 this->loadedHapPaths_[sPath] = std::vector<std::string>();
578 this->hapResources_.push_back(pResource);
579 if (pResource->HasDarkRes()) {
580 this->resConfig_->SetAppDarkRes(true);
581 }
582 return true;
583 }
584
585 #if defined(__ARKUI_CROSS__)
RemoveHapResource(const std::string & path)586 void HapManager::RemoveHapResource(const std::string &path)
587 {
588 for (auto iter = hapResources_.begin(); iter != hapResources_.end();) {
589 if ((*iter)->GetIndexPath() == path) {
590 iter = hapResources_.erase(iter);
591 break;
592 } else {
593 ++iter;
594 }
595 }
596
597 auto it = loadedHapPaths_.find(path);
598 if (it != loadedHapPaths_.end()) {
599 loadedHapPaths_.erase(it);
600 }
601 }
602 #endif
603
AddPatchResourcePath(const char * path,const char * patchPath)604 bool HapManager::AddPatchResourcePath(const char *path, const char *patchPath)
605 {
606 std::string sPath(path);
607 auto it = loadedHapPaths_.find(sPath);
608 if (it == loadedHapPaths_.end()) {
609 RESMGR_HILOGW(RESMGR_TAG, "AddPatchResourcePath hapPath not load, hapPath = %{public}s", sPath.c_str());
610 return false;
611 }
612 std::string sPatchPath(patchPath);
613 return HapResourceManager::GetInstance()->PutPatchResource(sPath, sPatchPath);
614 }
615
ReloadAll()616 RState HapManager::ReloadAll()
617 {
618 WriteLock lock(this->mutex_);
619 if (hapResources_.size() == 0) {
620 return SUCCESS;
621 }
622 std::vector<std::shared_ptr<HapResource>> newResources;
623 for (auto iter = loadedHapPaths_.begin(); iter != loadedHapPaths_.end(); iter++) {
624 std::vector<std::string> &overlayPaths = iter->second;
625 if (overlayPaths.size() == 0) {
626 const auto pResource = HapResource::Load(iter->first.c_str(), resConfig_);
627 if (pResource == nullptr) {
628 newResources.clear();
629 return HAP_INIT_FAILED;
630 }
631 newResources.push_back(pResource);
632 continue;
633 }
634 std::unordered_map<std::string, std::shared_ptr<HapResource>> result = HapResource::LoadOverlays(
635 iter->first.c_str(), overlayPaths, resConfig_);
636 if (result.size() == 0) {
637 continue;
638 }
639 for (auto iter = result.begin(); iter != result.end(); iter++) {
640 newResources.push_back(iter->second);
641 }
642 }
643 hapResources_.clear();
644 hapResources_ = newResources;
645 return SUCCESS;
646 }
647
GetResourcePaths()648 std::vector<std::string> HapManager::GetResourcePaths()
649 {
650 std::vector<std::string> result;
651 ReadLock lock(this->mutex_);
652 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
653 std::string indexPath = (*iter)->GetIndexPath();
654 auto index = indexPath.rfind('/');
655 if (index == std::string::npos) {
656 RESMGR_HILOGE(RESMGR_TAG, "index path format error, %s", indexPath.c_str());
657 continue;
658 }
659
660 result.emplace_back(indexPath.substr(0, index) + "/resources/");
661 }
662
663 return result;
664 }
665
GetImageType(const std::string fileName)666 std::string GetImageType(const std::string fileName)
667 {
668 auto pos = fileName.find_last_of('.');
669 std::string imgType;
670 if (pos != std::string::npos) {
671 imgType = fileName.substr(pos + 1);
672 }
673 return imgType;
674 }
675
676 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> & extractor,const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,const ResType resType)677 std::string GetFilePathFromHap(std::shared_ptr<AbilityBase::Extractor> &extractor,
678 const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, const ResType resType)
679 {
680 std::string filePath;
681 if (qd == nullptr) {
682 RESMGR_HILOGE(RESMGR_TAG, "GetFilePathFromHap qd is null");
683 return filePath;
684 }
685 const std::shared_ptr<IdItem> idItem = qd->GetIdItem();
686 if (idItem == nullptr || idItem->resType_ != resType) {
687 std::string hapPath = qd->GetIndexPath();
688 RESMGR_HILOGE(RESMGR_TAG, "actual resType = %{public}d, expect resType = %{public}d, hapPath = %{public}s",
689 idItem == nullptr ? -1 : idItem->resType_, resType, hapPath.c_str());
690 return filePath;
691 }
692 if (extractor->IsStageModel()) {
693 std::string tempFilePath(idItem->value_);
694 auto index = tempFilePath.find('/');
695 if (index == std::string::npos) {
696 RESMGR_HILOGE(RESMGR_TAG, "resource path format error, %s", tempFilePath.c_str());
697 return filePath;
698 }
699 filePath = idItem->value_.substr(index + 1);
700 } else {
701 // FA mode
702 std::string tempFilePath("assets/");
703 tempFilePath.append(idItem->value_);
704 filePath = tempFilePath;
705 }
706 return filePath;
707 }
708
GetAbilityExtractor(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd)709 std::shared_ptr<AbilityBase::Extractor> GetAbilityExtractor(
710 const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd)
711 {
712 std::string hapPath = qd->GetIndexPath();
713 bool isNewExtractor = false;
714 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
715 return extractor;
716 }
717 #endif
718
GetProfileData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)719 RState HapManager::GetProfileData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
720 std::unique_ptr<uint8_t[]> &outValue)
721 {
722 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
723 auto extractor = GetAbilityExtractor(qd);
724 if (extractor == nullptr) {
725 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
726 return NOT_FOUND;
727 }
728 std::string filePath = GetFilePathFromHap(extractor, qd, ResType::PROF);
729 if (filePath.empty()) {
730 RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetProfileData");
731 return NOT_FOUND;
732 }
733 bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
734 if (!ret) {
735 RESMGR_HILOGE(RESMGR_TAG, "failed to get config data from ability");
736 return NOT_FOUND;
737 }
738 #endif
739 return SUCCESS;
740 }
741
GetMediaData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)742 RState HapManager::GetMediaData(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
743 std::unique_ptr<uint8_t[]> &outValue)
744 {
745 std::string filePath = qd->GetIndexPath();
746 RState state;
747 if (Utils::ContainsTail(filePath, Utils::tailSet)) {
748 state = HapManager::GetMediaDataFromHap(qd, len, outValue);
749 } else {
750 state = HapManager::GetMediaDataFromIndex(qd, len, outValue);
751 }
752 return state;
753 }
754
GetMediaDataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)755 RState HapManager::GetMediaDataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
756 std::unique_ptr<uint8_t[]> &outValue)
757 {
758 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
759 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
760 auto extractor = GetAbilityExtractor(qd);
761 if (extractor == nullptr) {
762 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
763 return NOT_FOUND;
764 }
765 std::string filePath = GetFilePathFromHap(extractor, qd, ResType::MEDIA);
766 if (filePath.empty()) {
767 RESMGR_HILOGE(RESMGR_TAG, "get file path failed in GetMediaDataFromHap");
768 return NOT_FOUND;
769 }
770 bool ret = extractor->ExtractToBufByName(filePath, outValue, len);
771 if (!ret) {
772 RESMGR_HILOGE(RESMGR_TAG, "failed to get media data from ability");
773 return NOT_FOUND;
774 }
775 #endif
776 return SUCCESS;
777 }
778
GetMediaDataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,size_t & len,std::unique_ptr<uint8_t[]> & outValue)779 RState HapManager::GetMediaDataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd, size_t &len,
780 std::unique_ptr<uint8_t[]> &outValue)
781 {
782 std::string filePath;
783 RState state = HapManager::GetFilePath(qd, ResType::MEDIA, filePath);
784 if (state != SUCCESS) {
785 return NOT_FOUND;
786 }
787 outValue = Utils::LoadResourceFile(filePath, len);
788 return SUCCESS;
789 }
790
GetMediaBase64Data(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,std::string & outValue)791 RState HapManager::GetMediaBase64Data(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,
792 std::string &outValue)
793 {
794 std::string filePath = qd->GetIndexPath();
795 RState state;
796 if (Utils::ContainsTail(filePath, Utils::tailSet)) {
797 state = HapManager::GetMediaBase64DataFromHap(qd, outValue);
798 } else {
799 state = HapManager::GetMediaBase64DataFromIndex(qd, outValue);
800 }
801 return state;
802 }
803
GetMediaBase64DataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,std::string & outValue)804 RState HapManager::GetMediaBase64DataFromHap(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,
805 std::string &outValue)
806 {
807 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
808 auto extractor = GetAbilityExtractor(qd);
809 if (extractor == nullptr) {
810 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor from ability");
811 return NOT_FOUND;
812 }
813 std::string filePath = GetFilePathFromHap(extractor, qd, ResType::MEDIA);
814 std::unique_ptr<uint8_t[]> buffer;
815 size_t tmpLen;
816 bool ret = extractor->ExtractToBufByName(filePath, buffer, tmpLen);
817 if (!ret) {
818 RESMGR_HILOGE(RESMGR_TAG, "failed to get mediabase64 data from ability");
819 return NOT_FOUND;
820 }
821 std::string imgType = GetImageType(filePath);
822 Utils::EncodeBase64(buffer, tmpLen, imgType, outValue);
823 #endif
824 return SUCCESS;
825 }
826
GetMediaBase64DataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,std::string & outValue)827 RState HapManager::GetMediaBase64DataFromIndex(const std::shared_ptr<HapResource::ValueUnderQualifierDir> qd,
828 std::string &outValue)
829 {
830 std::string filePath;
831 RState state = HapManager::GetFilePath(qd, ResType::MEDIA, filePath);
832 if (state != SUCCESS) {
833 return NOT_FOUND;
834 }
835 return Utils::GetMediaBase64Data(filePath, outValue);
836 }
837
GetValidHapPath(std::string & hapPath)838 int32_t HapManager::GetValidHapPath(std::string &hapPath)
839 {
840 ReadLock lock(this->mutex_);
841 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
842 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
843 continue;
844 }
845 const std::string tempPath = (*iter)->GetIndexPath();
846 if (Utils::ContainsTail(tempPath, Utils::tailSet)) {
847 hapPath = tempPath;
848 return OK;
849 }
850 }
851 return NOT_FOUND;
852 }
853
GetValidIndexPath(std::string & indexPath)854 int32_t HapManager::GetValidIndexPath(std::string &indexPath)
855 {
856 ReadLock lock(this->mutex_);
857 for (auto iter = hapResources_.rbegin(); iter != hapResources_.rend(); iter++) {
858 const std::string tempPath = (*iter)->GetIndexPath();
859 if (Utils::endWithTail(tempPath, "/systemres/resources.index")) {
860 continue;
861 }
862 indexPath = tempPath;
863 return OK;
864 }
865 return NOT_FOUND;
866 }
867
FindRawFileFromHap(const std::string & rawFileName,size_t & len,std::unique_ptr<uint8_t[]> & outValue)868 RState HapManager::FindRawFileFromHap(const std::string &rawFileName, size_t &len,
869 std::unique_ptr<uint8_t[]> &outValue)
870 {
871 ReadLock lock(this->mutex_);
872 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
873 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
874 continue;
875 }
876 std::string tempPath = (*iter)->GetIndexPath();
877 std::string tempPatchPath;
878 if ((*iter)->IsPatch()) {
879 tempPatchPath = (*iter)->GetPatchPath();
880 }
881 if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
882 RState state = HapParser::ReadRawFileFromHap(tempPath, tempPatchPath, rawFileName, len, outValue);
883 if (state != SUCCESS) {
884 continue;
885 }
886 } else { // if file path is uncompressed
887 std::string filePath;
888 HapManager::FindRawFile(rawFileName, filePath);
889 outValue = Utils::LoadResourceFile(filePath, len);
890 if (outValue == nullptr) {
891 continue;
892 }
893 }
894 return SUCCESS;
895 }
896 return ERROR_CODE_RES_PATH_INVALID;
897 }
898
FindRawFileDescriptorFromHap(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)899 RState HapManager::FindRawFileDescriptorFromHap(const std::string &rawFileName,
900 ResourceManager::RawFileDescriptor &descriptor)
901 {
902 std::lock_guard<std::mutex> lock(g_rawFileLock);
903 auto it = rawFileDescriptor_.find(rawFileName);
904 if (it != rawFileDescriptor_.end()) {
905 descriptor.fd = rawFileDescriptor_[rawFileName].fd;
906 descriptor.length = rawFileDescriptor_[rawFileName].length;
907 descriptor.offset = rawFileDescriptor_[rawFileName].offset;
908 return SUCCESS;
909 }
910 RState state = GetRawFd(rawFileName, descriptor);
911 if (state == SUCCESS) {
912 rawFileDescriptor_[rawFileName] = descriptor;
913 }
914 return state;
915 }
916
GetRawFd(const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)917 RState HapManager::GetRawFd(const std::string &rawFileName, ResourceManager::RawFileDescriptor &descriptor)
918 {
919 RState state;
920 ReadLock lock(this->mutex_);
921 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
922 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
923 continue;
924 }
925 std::string tempPath = (*iter)->GetIndexPath();
926 std::string tempPatchPath;
927 if ((*iter)->IsPatch()) {
928 tempPatchPath = (*iter)->GetPatchPath();
929 }
930 if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
931 state = HapParser::ReadRawFileDescriptor(tempPath.c_str(), tempPatchPath.c_str(), rawFileName, descriptor);
932 } else { // if file path is uncompressed
933 state = HapManager::FindRawFileDescriptor(rawFileName, descriptor);
934 }
935 if (state != SUCCESS) {
936 continue;
937 }
938 return SUCCESS;
939 }
940 return ERROR_CODE_RES_PATH_INVALID;
941 }
942
GetRawFileList(const std::string & rawDirPath,std::vector<std::string> & fileList)943 RState HapManager::GetRawFileList(const std::string &rawDirPath, std::vector<std::string> &fileList)
944 {
945 std::string hapOrIndexPath;
946 if (HapManager::GetValidHapPath(hapOrIndexPath) == OK) {
947 std::string temPatchPath;
948 {
949 ReadLock lock(this->mutex_);
950 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
951 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
952 continue;
953 }
954 if ((*iter)->GetIndexPath() == hapOrIndexPath && (*iter)->IsPatch()) {
955 temPatchPath = (*iter)->GetPatchPath();
956 }
957 }
958 }
959 std::set<std::string> fileSet;
960 RState hapState = HapParser::GetRawFileList(hapOrIndexPath, rawDirPath, fileSet);
961 RState hqfState = NOT_FOUND;
962 if (!temPatchPath.empty()) {
963 hqfState = HapParser::GetRawFileList(temPatchPath, rawDirPath, fileSet);
964 }
965 for (auto it = fileSet.begin(); it != fileSet.end(); it++) {
966 fileList.emplace_back(*it);
967 }
968 return (hapState != SUCCESS && hqfState != SUCCESS) ? ERROR_CODE_RES_PATH_INVALID : SUCCESS;
969 }
970 if (HapManager::GetValidIndexPath(hapOrIndexPath) == OK) {
971 return HapParser::GetRawFileListUnCompressed(hapOrIndexPath, rawDirPath, fileList);
972 }
973 return ERROR_CODE_RES_PATH_INVALID;
974 }
975
IsLoadHap(std::string & hapPath)976 bool HapManager::IsLoadHap(std::string &hapPath)
977 {
978 return HapManager::GetValidHapPath(hapPath) == OK ? true : false;
979 }
980
GetFilePath(const std::shared_ptr<HapResource::ValueUnderQualifierDir> vuqd,const ResType resType,std::string & outValue)981 RState HapManager::GetFilePath(const std::shared_ptr<HapResource::ValueUnderQualifierDir> vuqd, const ResType resType,
982 std::string &outValue)
983 {
984 // not found or type invalid
985 if (vuqd == nullptr) {
986 return NOT_FOUND;
987 }
988 const std::shared_ptr<IdItem> idItem = vuqd->GetIdItem();
989 if (idItem == nullptr || idItem->resType_ != resType) {
990 return NOT_FOUND;
991 }
992 outValue = vuqd->GetResourcePath();
993 #if defined(__ARKUI_CROSS__)
994 auto index = idItem->value_.find('/');
995 if (index == std::string::npos) {
996 RESMGR_HILOGE(RESMGR_TAG, "resource path format error, %s", idItem->value_.c_str());
997 return NOT_FOUND;
998 }
999 auto nameWithoutModule = idItem->value_.substr(index + 1);
1000 outValue.append(nameWithoutModule);
1001 #elif defined(__IDE_PREVIEW__)
1002 if (Utils::IsFileExist(idItem->value_)) {
1003 outValue = idItem->value_;
1004 return SUCCESS;
1005 }
1006 auto index = idItem->value_.find('/');
1007 if (index == std::string::npos) {
1008 RESMGR_HILOGE(RESMGR_TAG, "resource path format error, %s", idItem->value_.c_str());
1009 return NOT_FOUND;
1010 }
1011 auto nameWithoutModule = idItem->value_.substr(index + 1);
1012 outValue.append(nameWithoutModule);
1013 #else
1014 outValue.append(idItem->value_);
1015 #endif
1016 return SUCCESS;
1017 }
1018
FindRawFileDescriptor(const std::string & name,ResourceManager::RawFileDescriptor & descriptor)1019 RState HapManager::FindRawFileDescriptor(const std::string &name, ResourceManager::RawFileDescriptor &descriptor)
1020 {
1021 std::string paths = "";
1022 RState rState = HapManager::FindRawFile(name, paths);
1023 if (rState != SUCCESS) {
1024 return rState;
1025 }
1026 char outPath[PATH_MAX + 1] = {0};
1027 Utils::CanonicalizePath(paths.c_str(), outPath, PATH_MAX);
1028 int fd = open(outPath, O_RDONLY);
1029 if (fd > 0) {
1030 long length = lseek(fd, 0, SEEK_END);
1031 if (length == -1) {
1032 close(fd);
1033 return ERROR_CODE_RES_PATH_INVALID;
1034 }
1035 long begin = lseek(fd, 0, SEEK_SET);
1036 if (begin == -1) {
1037 close(fd);
1038 return ERROR_CODE_RES_PATH_INVALID;
1039 }
1040 descriptor.fd = fd;
1041 descriptor.length = length;
1042 descriptor.offset = 0;
1043 return SUCCESS;
1044 }
1045 return ERROR_CODE_RES_PATH_INVALID;
1046 }
1047
CloseRawFileDescriptor(const std::string & name)1048 RState HapManager::CloseRawFileDescriptor(const std::string &name)
1049 {
1050 std::lock_guard<std::mutex> lock(g_rawFileLock);
1051 auto it = rawFileDescriptor_.find(name);
1052 if (it == rawFileDescriptor_.end()) {
1053 return ERROR_CODE_RES_PATH_INVALID;
1054 }
1055
1056 int fd = rawFileDescriptor_[name].fd;
1057 if (fd <= 0) {
1058 return ERROR_CODE_RES_PATH_INVALID;
1059 }
1060
1061 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
1062 if (fdsan_get_owner_tag(fd) != 0) {
1063 rawFileDescriptor_.erase(name);
1064 return SUCCESS;
1065 }
1066 #endif
1067
1068 if (close(fd) == -1) {
1069 return ERROR_CODE_RES_PATH_INVALID;
1070 }
1071
1072 rawFileDescriptor_.erase(name);
1073 return SUCCESS;
1074 }
1075
RemoveResource(const std::string & path,const std::vector<std::string> & overlayPaths)1076 bool HapManager::RemoveResource(const std::string &path, const std::vector<std::string> &overlayPaths)
1077 {
1078 WriteLock lock(this->mutex_);
1079 RESMGR_HILOGI(RESMGR_TAG, "remove overlay for path, %{public}s", path.c_str());
1080 if (loadedHapPaths_.find(path) == loadedHapPaths_.end()) {
1081 return false;
1082 }
1083 std::vector<std::string> targetOverlay = loadedHapPaths_[path];
1084 if (targetOverlay.empty()) {
1085 RESMGR_HILOGE(RESMGR_TAG, "the %{public}s have not overlay", path.c_str());
1086 return false;
1087 }
1088 char outPath[PATH_MAX] = {0};
1089 for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
1090 Utils::CanonicalizePath((*iter).c_str(), outPath, PATH_MAX);
1091 if (outPath[0] == '\0') {
1092 RESMGR_HILOGE(RESMGR_TAG, "invalid overlayPath, %{public}s", (*iter).c_str());
1093 continue;
1094 }
1095 if (std::find(targetOverlay.begin(), targetOverlay.end(), outPath) != targetOverlay.end()) {
1096 targetOverlay.erase(std::remove(targetOverlay.begin(), targetOverlay.end(), outPath),
1097 targetOverlay.end());
1098 }
1099 for (auto resIter = hapResources_.begin(); resIter != hapResources_.end();) {
1100 if ((*resIter) == nullptr) {
1101 RESMGR_HILOGE(RESMGR_TAG, "hapResource is nullptr");
1102 return false;
1103 }
1104 std::string hapPath = (*resIter)->GetIndexPath();
1105 if (hapPath == outPath) {
1106 resIter = hapResources_.erase(resIter);
1107 } else {
1108 resIter++;
1109 }
1110 }
1111 }
1112 loadedHapPaths_[path] = targetOverlay;
1113 return true;
1114 }
1115
GetHapResource()1116 std::vector<std::shared_ptr<HapResource>> HapManager::GetHapResource()
1117 {
1118 return hapResources_;
1119 }
1120
AddSystemResource(const std::shared_ptr<HapManager> & systemHapManager)1121 void HapManager::AddSystemResource(const std::shared_ptr<HapManager> &systemHapManager)
1122 {
1123 if (systemHapManager == nullptr) {
1124 RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, systemHapManager is nullptr");
1125 return;
1126 }
1127 if (!systemHapManager->isSystem_) {
1128 RESMGR_HILOGE(RESMGR_TAG, "add system resource failed, the added hapManager is not system");
1129 return;
1130 }
1131 WriteLock lock(this->mutex_);
1132 // add system resource to app resource vector
1133 const std::vector<std::shared_ptr<HapResource>> &systemResources = systemHapManager->hapResources_;
1134 for (size_t i = 0; i < systemResources.size(); i++) {
1135 this->hapResources_.push_back(systemResources[i]);
1136 }
1137
1138 // add system loaded path to app loaded path map.
1139 const std::unordered_map<std::string, std::vector<std::string>> &loadedSystemPaths =
1140 systemHapManager->loadedHapPaths_;
1141 for (auto iter = loadedSystemPaths.begin(); iter != loadedSystemPaths.end(); iter++) {
1142 const std::vector<std::string> &overlayPaths = iter->second;
1143 if (this->loadedHapPaths_.find(iter->first) == this->loadedHapPaths_.end()) {
1144 this->loadedHapPaths_[iter->first] = overlayPaths;
1145 }
1146 }
1147 }
1148
GetResourceLimitKeys()1149 uint32_t HapManager::GetResourceLimitKeys()
1150 {
1151 ReadLock lock(this->mutex_);
1152 uint32_t limitKeysValue = 0;
1153 for (size_t i = 0; i < hapResources_.size(); i++) {
1154 limitKeysValue |= hapResources_[i]->GetResourceLimitKeys();
1155 }
1156 RESMGR_HILOGD(RESMGR_TAG, "hap manager limit key is %{public}u", limitKeysValue);
1157 return limitKeysValue;
1158 }
1159
1160 std::unordered_map<std::string, ResType> ResTypeMap {
1161 {"integer", INTEGER},
1162 {"string", STRING},
1163 {"strarray", STRINGARRAY},
1164 {"intarray", INTARRAY},
1165 {"boolean", BOOLEAN},
1166 {"color", COLOR},
1167 {"theme", THEME},
1168 {"plural", PLURALS},
1169 {"float", FLOAT},
1170 {"media", MEDIA},
1171 {"profile", PROF},
1172 {"pattern", PATTERN},
1173 };
1174
IsPrefix(std::string_view prefix,std::string_view full)1175 bool IsPrefix(std::string_view prefix, std::string_view full)
1176 {
1177 return prefix == full.substr(0, prefix.size());
1178 }
1179
GetRealResId(const std::string & resType,const std::vector<std::unordered_map<ResType,uint32_t>> & candidates)1180 uint32_t GetRealResId(const std::string &resType,
1181 const std::vector<std::unordered_map<ResType, uint32_t>> &candidates)
1182 {
1183 for (auto candidate : candidates) {
1184 for (auto data : candidate) {
1185 if (ResTypeMap.find(resType) != ResTypeMap.end() && ResTypeMap[resType] == data.first) {
1186 return data.second;
1187 }
1188 }
1189 }
1190 return 0;
1191 }
1192
GetResTypeAndResName(const std::string & resTypeName)1193 std::tuple<std::string, std::string> GetResTypeAndResName(const std::string &resTypeName)
1194 {
1195 std::tuple<std::string, std::string> typeNameTuple;
1196 auto pos1 = resTypeName.find('.');
1197 auto pos2 = resTypeName.rfind('.');
1198 if (pos1 == std::string::npos || pos2 == std::string::npos) {
1199 return std::make_tuple("", "");
1200 }
1201 if (pos2 < pos1 + 1) {
1202 return std::make_tuple("", "");
1203 }
1204 const std::string resType = resTypeName.substr(pos1 + 1, pos2 - pos1 - 1);
1205 if (ResTypeMap.find(resType) == ResTypeMap.end()) {
1206 return std::make_tuple("", "");
1207 }
1208 const std::string resName = resTypeName.substr(pos2 + 1);
1209 if (resName.empty()) {
1210 return std::make_tuple("", "");
1211 }
1212 typeNameTuple = std::make_tuple(resType, resName);
1213 return typeNameTuple;
1214 }
1215
GetResId(const std::string & resTypeName,uint32_t & resId)1216 RState HapManager::GetResId(const std::string &resTypeName, uint32_t &resId)
1217 {
1218 auto typeNameTuple = GetResTypeAndResName(resTypeName);
1219 const std::string resType = std::get<0>(typeNameTuple);
1220 const std::string resName = std::get<1>(typeNameTuple);
1221 if (resType.empty() || resName.empty()) {
1222 RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1223 return NOT_FOUND;
1224 }
1225 bool isSystem = IsPrefix("sys", resTypeName);
1226 bool isApp = IsPrefix("app", resTypeName);
1227 if (!isSystem && !isApp) {
1228 RESMGR_HILOGE(RESMGR_TAG, "invalid resTypeName = %{public}s", resTypeName.c_str());
1229 return NOT_FOUND;
1230 }
1231 ReadLock lock(this->mutex_);
1232 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1233 bool isSystemResource = (*iter)->IsSystemResource();
1234 bool isOverlayResource = (*iter)->IsOverlayResource();
1235 if (isOverlayResource) {
1236 continue;
1237 }
1238 if (isSystem && !isSystemResource) {
1239 continue;
1240 }
1241 if (isApp && isSystemResource) {
1242 continue;
1243 }
1244 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> nameTypeIdMap =
1245 (*iter)->BuildNameTypeIdMapping();
1246 std::vector<std::unordered_map<ResType, uint32_t>> candidates;
1247 for (auto data : nameTypeIdMap) {
1248 if (data.first != resName) {
1249 continue;
1250 }
1251 candidates.emplace_back(data.second);
1252 }
1253 resId = GetRealResId(resType, candidates);
1254 if (resId == 0) {
1255 RESMGR_HILOGE(RESMGR_TAG,
1256 "GetResId name = %{public}s, resType = %{public}s", resName.c_str(), resType.c_str());
1257 return NOT_FOUND;
1258 }
1259 }
1260 return SUCCESS;
1261 }
1262
GetLocales(std::vector<std::string> & outValue,bool includeSystem)1263 void HapManager::GetLocales(std::vector<std::string> &outValue, bool includeSystem)
1264 {
1265 if (isSystem_) {
1266 includeSystem = true;
1267 }
1268 std::set<std::string> result;
1269 ReadLock lock(this->mutex_);
1270 for (size_t i = 0; i < hapResources_.size(); i++) {
1271 hapResources_[i]->GetLocales(result, includeSystem);
1272 }
1273 outValue.assign(result.begin(), result.end());
1274 }
1275
IsRawDirFromHap(const std::string & pathName,bool & outValue)1276 RState HapManager::IsRawDirFromHap(const std::string &pathName, bool &outValue)
1277 {
1278 ReadLock lock(this->mutex_);
1279 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1280 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
1281 continue;
1282 }
1283 const std::string tempPath = (*iter)->GetIndexPath();
1284 if (Utils::ContainsTail(tempPath, Utils::tailSet)) { // if file path is compressed
1285 RState state = HapParser::IsRawDirFromHap(tempPath.c_str(), pathName, outValue);
1286 if (state != SUCCESS) {
1287 continue;
1288 }
1289 } else { // if file path is uncompressed
1290 #if !defined(__ARKUI_CROSS__)
1291 RState state = HapParser::IsRawDirUnCompressed(pathName, outValue);
1292 if (state != SUCCESS) {
1293 continue;
1294 }
1295 #else
1296 const std::string finalPath = (*iter)->GetResourcePath() + RAW_FILE_PATH + pathName;
1297 RState state = HapParser::IsRawDirUnCompressed(finalPath, outValue);
1298 if (state != SUCCESS) {
1299 continue;
1300 }
1301 #endif
1302 }
1303 return SUCCESS;
1304 }
1305 return ERROR_CODE_RES_PATH_INVALID;
1306 }
1307
IsThemeSystemResEnableHap()1308 bool HapManager::IsThemeSystemResEnableHap()
1309 {
1310 ReadLock lock(this->mutex_);
1311 for (auto iter = hapResources_.begin(); iter != hapResources_.end(); iter++) {
1312 if ((*iter)->IsSystemResource() || (*iter)->IsOverlayResource()) {
1313 continue;
1314 }
1315 if ((*iter)->IsThemeSystemResEnable()) {
1316 return true;
1317 }
1318 }
1319 return false;
1320 }
1321
IsSystem()1322 bool HapManager::IsSystem()
1323 {
1324 return this->isSystem_;
1325 }
1326
GetLoadedHapPaths()1327 std::unordered_map<std::string, std::vector<std::string>> HapManager::GetLoadedHapPaths()
1328 {
1329 return this->loadedHapPaths_;
1330 }
1331 } // namespace Resource
1332 } // namespace Global
1333 } // namespace OHOS
1334