• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #include "hap_resource_v1.h"
17 
18 #include <algorithm>
19 #include <climits>
20 #include <cstdlib>
21 #include <fstream>
22 #include "utils/utils.h"
23 #include <set>
24 #ifdef __WINNT__
25 #include <shlwapi.h>
26 #include <windows.h>
27 #undef GetLocaleInfo
28 #endif
29 
30 #ifdef __LINUX__
31 #include <cstring>
32 #endif
33 
34 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
35 #include "hitrace_meter.h"
36 #include "file_mapper.h"
37 #include "extractor.h"
38 #endif
39 
40 #include "hap_parser_v1.h"
41 #include "hap_resource_manager.h"
42 #include "hilog_wrapper.h"
43 #include "utils/errors.h"
44 
45 using ReadLock = std::shared_lock<std::shared_mutex>;
46 using WriteLock = std::unique_lock<std::shared_mutex>;
47 
48 namespace OHOS {
49 namespace Global {
50 namespace Resource {
ValueUnderQualifierDirV1(const std::shared_ptr<ResKey> & resKey,const std::shared_ptr<IdItem> & idItem,const std::pair<std::string,std::string> & resPath,bool isOverlay,bool systemResource)51 ValueUnderQualifierDirV1::ValueUnderQualifierDirV1(const std::shared_ptr<ResKey> &resKey,
52     const std::shared_ptr<IdItem> &idItem, const std::pair<std::string, std::string> &resPath, bool isOverlay,
53     bool systemResource) : ValueUnderQualifierDir(resPath, resKey->resConfig_, isOverlay, systemResource),
54     idItem_(idItem)
55 {}
56 
~ValueUnderQualifierDirV1()57 ValueUnderQualifierDirV1::~ValueUnderQualifierDirV1()
58 {}
59 
GetIdItem() const60 std::shared_ptr<IdItem> ValueUnderQualifierDirV1::GetIdItem() const
61 {
62     return idItem_;
63 }
64 
~IdValuesV1()65 IdValuesV1::~IdValuesV1()
66 {}
67 
GetLimitPathsConst() const68 const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &IdValuesV1::GetLimitPathsConst() const
69 {
70     return limitPaths_;
71 }
72 
HapResourceV1(const std::string path,time_t lastModTime,std::shared_ptr<ResDesc> resDes,bool isSystem,bool isOverlay)73 HapResourceV1::HapResourceV1(const std::string path, time_t lastModTime, std::shared_ptr<ResDesc> resDes,
74     bool isSystem, bool isOverlay) : HapResource(path, lastModTime), resDesc_(resDes),
75     isSystem_(isSystem), isOverlay_(isOverlay)
76 {}
77 
~HapResourceV1()78 HapResourceV1::~HapResourceV1()
79 {}
80 
Init(std::shared_ptr<ResConfigImpl> & defaultConfig)81 bool HapResourceV1::Init(std::shared_ptr<ResConfigImpl> &defaultConfig)
82 {
83 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
84     HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
85 #endif
86 #ifdef __WINNT__
87     char separator = '\\';
88 #else
89     char separator = '/';
90 #endif
91     auto index = indexPath_.rfind(separator);
92     if (index == std::string::npos) {
93         RESMGR_HILOGE(RESMGR_TAG, "index path format error");
94         return false;
95     }
96 #if defined(__IDE_PREVIEW__) || defined(__ARKUI_CROSS__)
97     resourcePath_ = indexPath_.substr(0, index + 1);
98 #else
99     if (index < 1) {
100         return false;
101     }
102     index = indexPath_.rfind(separator, index - 1);
103     if (index == std::string::npos) {
104         RESMGR_HILOGE(RESMGR_TAG, "index path format error");
105         return false;
106     }
107     resourcePath_ = indexPath_.substr(0, index + 1);
108 #endif
109     for (int i = 0; i < ResType::MAX_RES_TYPE; ++i) {
110         auto mptr = std::make_shared<std::map<std::string, std::shared_ptr<IdValuesV1>>>();
111         idValuesNameMap_.push_back(mptr);
112     }
113     WriteLock lock(mutex_);
114     return InitIdList(defaultConfig);
115 }
116 
IsSystemResource() const117 bool HapResourceV1::IsSystemResource() const
118 {
119     return isSystem_;
120 }
121 
IsOverlayResource() const122 bool HapResourceV1::IsOverlayResource() const
123 {
124     return isOverlay_;
125 }
126 
GetIdValues(const uint32_t id)127 const std::shared_ptr<IdValues> HapResourceV1::GetIdValues(const uint32_t id)
128 {
129     ReadLock lock(mutex_);
130     if (idValuesMap_.empty()) {
131         RESMGR_HILOGE(RESMGR_TAG, "idValuesMap_ is empty");
132         return nullptr;
133     }
134     uint32_t uid = id;
135     std::map<uint32_t, std::shared_ptr<IdValuesV1>>::const_iterator iter = idValuesMap_.find(uid);
136     if (iter == idValuesMap_.end()) {
137         return nullptr;
138     }
139     return iter->second;
140 }
141 
GetIdValuesByName(const std::string name,const ResType resType)142 const std::shared_ptr<IdValues> HapResourceV1::GetIdValuesByName(
143     const std::string name, const ResType resType)
144 {
145     ReadLock lock(mutex_);
146     const auto map = idValuesNameMap_[resType];
147     std::map<std::string, std::shared_ptr<IdValuesV1>>::const_iterator iter = map->find(name);
148     if (iter == map->end()) {
149         return nullptr;
150     }
151     return iter->second;
152 }
153 
Update(std::shared_ptr<ResConfigImpl> & defaultConfig)154 RState HapResourceV1::Update(std::shared_ptr<ResConfigImpl> &defaultConfig)
155 {
156     return this->UpdateResConfig(defaultConfig);
157 }
158 
BuildNameTypeIdMapping()159 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> HapResourceV1::BuildNameTypeIdMapping()
160 {
161     ReadLock lock(mutex_);
162     std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> result;
163     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
164         const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &limitPaths = iter->second->GetLimitPathsConst();
165         if (limitPaths.size() > 0) {
166             std::shared_ptr<ValueUnderQualifierDirV1> value =
167                 std::static_pointer_cast<ValueUnderQualifierDirV1>(limitPaths[0]);
168             result[value->idItem_->name_][value->idItem_->resType_] = value->idItem_->id_;
169         }
170     }
171     return result;
172 }
173 
GetLocales(std::set<std::string> & outValue,bool includeSystem)174 void HapResourceV1::GetLocales(std::set<std::string> &outValue, bool includeSystem)
175 {
176     ReadLock lock(mutex_);
177     if (resDesc_ == nullptr) {
178         RESMGR_HILOGE(RESMGR_TAG, "resDesc_ is null! GetLocales failed");
179         return;
180     }
181     if ((!includeSystem && isSystem_) || (!isSystem_ && isOverlay_)) {
182         return;
183     }
184     outValue.insert(locales_.begin(), locales_.end());
185 }
186 
UpdateOverlayInfo(std::unordered_map<std::string,std::unordered_map<ResType,uint32_t>> & nameTypeId)187 void HapResourceV1::UpdateOverlayInfo(
188     std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> &nameTypeId)
189 {
190     WriteLock lock(mutex_);
191     std::map<uint32_t, std::shared_ptr<IdValuesV1>> newIdValuesMap;
192     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
193         const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &limitPaths = iter->second->GetLimitPathsConst();
194         if (limitPaths.size() > 0) {
195             std::shared_ptr<ValueUnderQualifierDirV1> value =
196                 std::static_pointer_cast<ValueUnderQualifierDirV1>(limitPaths[0]);
197             std::string name = value->idItem_->name_;
198             ResType type = value->idItem_->resType_;
199             if (nameTypeId.find(name) == nameTypeId.end()) {
200                 continue;
201             }
202             auto &typeId = nameTypeId[name];
203             if (typeId.find(type) == typeId.end()) {
204                 continue;
205             }
206             uint32_t newId = typeId[type];
207             for_each(limitPaths.begin(), limitPaths.end(), [&](auto &item) {
208                 item->GetIdItem()->id_ = newId;
209             });
210             newIdValuesMap[newId] = iter->second;
211         }
212     }
213     idValuesMap_.swap(newIdValuesMap);
214 }
215 
InitIdList(std::shared_ptr<ResConfigImpl> & defaultConfig)216 bool HapResourceV1::InitIdList(std::shared_ptr<ResConfigImpl> &defaultConfig)
217 {
218 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
219     HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
220 #endif
221     if (resDesc_ == nullptr) {
222         RESMGR_HILOGE(RESMGR_TAG, "resDesc_ is null ! InitIdList failed");
223         return false;
224     }
225     const auto resPath = std::make_pair(indexPath_, resourcePath_);
226     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
227         const auto resKey = resDesc_->keys_[i];
228         if (!InitMap(resKey, resPath, defaultConfig)) {
229             return false;
230         }
231     }
232 #ifdef SUPPORT_GRAPHICS
233     if (defaultConfig && (defaultConfig->GetPreferredLocaleInfo() || defaultConfig->GetLocaleInfo())) {
234         std::shared_ptr<ResConfigImpl> currentConfig = std::make_shared<ResConfigImpl>();
235         currentConfig->Copy(*defaultConfig);
236         loadedConfig_.insert(currentConfig);
237     }
238 #endif
239     return true;
240 };
241 
InitMap(const std::shared_ptr<ResKey> & resKey,const std::pair<std::string,std::string> & resPath,std::shared_ptr<ResConfigImpl> & defaultConfig)242 bool HapResourceV1::InitMap(const std::shared_ptr<ResKey> &resKey, const std::pair<std::string, std::string> &resPath,
243     std::shared_ptr<ResConfigImpl> &defaultConfig)
244 {
245     for (size_t j = 0; j < resKey->resId_->idParams_.size(); ++j) {
246         std::shared_ptr<IdParam> idParam = resKey->resId_->idParams_[j];
247         uint32_t id = idParam->id_;
248         std::map<uint32_t, std::shared_ptr<IdValuesV1>>::iterator iter = idValuesMap_.find(id);
249         if (iter == idValuesMap_.end()) {
250             auto idValues = std::make_shared<IdValuesV1>();
251             if (idValues == nullptr) {
252                 RESMGR_HILOGE(RESMGR_TAG, "new IdValues failed in HapResource::InitIdList");
253                 return false;
254             }
255             auto limitPath = std::make_shared<ValueUnderQualifierDirV1>(resKey,
256                 idParam->idItem_, resPath, isOverlay_, isSystem_);
257             if (limitPath == nullptr) {
258                 RESMGR_HILOGE(RESMGR_TAG, "new ValueUnderQualifierDir failed in HapResource::InitIdList");
259                 return false;
260             }
261             idValues->AddLimitPath(limitPath);
262             IsAppDarkRes(limitPath, defaultConfig);
263             idValuesMap_.insert(std::make_pair(id, idValues));
264             std::string name = std::string(idParam->idItem_->name_);
265             idValuesNameMap_[idParam->idItem_->resType_]->insert(std::make_pair(name, idValues));
266             if (name == "system_color_change" && idParam->idItem_->value_ == "true") {
267                 isThemeSystemResEnable_ = true;
268             }
269         } else {
270             std::shared_ptr<IdValuesV1> idValues = iter->second;
271             auto limitPath = std::make_shared<ValueUnderQualifierDirV1>(resKey,
272                 idParam->idItem_, resPath, isOverlay_, isSystem_);
273             if (limitPath == nullptr) {
274                 RESMGR_HILOGE(RESMGR_TAG, "new ValueUnderQualifierDir failed in HapResource::InitIdList");
275                 return false;
276             }
277             idValues->AddLimitPath(limitPath);
278             IsAppDarkRes(limitPath, defaultConfig);
279         }
280     }
281     return true;
282 }
283 
IsAppDarkRes(const std::shared_ptr<ValueUnderQualifierDir> & limitPath,std::shared_ptr<ResConfigImpl> & defaultConfig)284 void HapResourceV1::IsAppDarkRes(const std::shared_ptr<ValueUnderQualifierDir> &limitPath,
285     std::shared_ptr<ResConfigImpl> &defaultConfig)
286 {
287     if (!defaultConfig) {
288         return;
289     }
290     if (isSystem_ || isOverlay_ || defaultConfig->GetAppDarkRes()) {
291         return;
292     }
293 
294     if (limitPath->GetResConfig()->GetColorMode() == ColorMode::DARK) {
295         defaultConfig->SetAppDarkRes(true);
296         hasDarkRes_ = true;
297     }
298 }
299 
UpdateResConfig(std::shared_ptr<ResConfigImpl> & defaultConfig)300 RState HapResourceV1::UpdateResConfig(std::shared_ptr<ResConfigImpl> &defaultConfig)
301 {
302     if (isSystem_ || isOverlay_ || !defaultConfig) {
303         return SUCCESS;
304     }
305 #ifdef SUPPORT_GRAPHICS
306     if (!defaultConfig->GetPreferredLocaleInfo() && !defaultConfig->GetLocaleInfo()) {
307         return SUCCESS;
308     }
309 #endif
310     WriteLock lock(mutex_);
311     for (auto &config : loadedConfig_) {
312         if (defaultConfig->MatchLocal(*config)) {
313             return SUCCESS;
314         }
315     }
316 
317     HapParserV1 hapParser(defaultConfig, selectedTypes_, false, true);
318     resDesc_ = std::make_shared<ResDesc>();
319     hapParser.SetResDesc(resDesc_);
320     if (!hapParser.Init(indexPath_.c_str())) {
321         return HAP_INIT_FAILED;
322     }
323     if (!InitIdList(defaultConfig)) {
324         return HAP_INIT_FAILED;
325     }
326     return SUCCESS;
327 }
328 }
329 }
330 }