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_v2.h"
17
18 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
19 #include <sys/mman.h>
20 #endif
21 #include <unistd.h>
22
23 #include "hap_parser_v2.h"
24
25 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
26 #include "hitrace_meter.h"
27 #endif
28
29 #include "hilog_wrapper.h"
30 #include "utils/errors.h"
31
32 using ReadLock = std::shared_lock<std::shared_mutex>;
33 using WriteLock = std::unique_lock<std::shared_mutex>;
34
35 namespace OHOS {
36 namespace Global {
37 namespace Resource {
ValueUnderQualifierDirV2(const std::pair<std::string,std::string> & resPath,uint32_t offset,std::shared_ptr<ResConfigImpl> resConfig,bool isOverlay,bool isSystemResource)38 ValueUnderQualifierDirV2::ValueUnderQualifierDirV2(const std::pair<std::string, std::string> &resPath,
39 uint32_t offset, std::shared_ptr<ResConfigImpl> resConfig, bool isOverlay, bool isSystemResource)
40 : ValueUnderQualifierDir(resPath, resConfig, isOverlay, isSystemResource), offset_(offset)
41 {}
42
~ValueUnderQualifierDirV2()43 ValueUnderQualifierDirV2::~ValueUnderQualifierDirV2()
44 {}
45
GetIdItem() const46 std::shared_ptr<IdItem> ValueUnderQualifierDirV2::GetIdItem() const
47 {
48 std::shared_ptr<IdItem> idItem = std::make_shared<IdItem>();
49 idItem->resType_ = resType_;
50 idItem->id_ = id_;
51 idItem->name_ = name_;
52
53 uint32_t offset = offset_;
54 idItem->JudgeArray();
55 if (idItem->isArray_) {
56 if (HapParserV2::ParseStringArray(offset, idItem->values_, mMapFile_->mmapLen_, mMapFile_->mmap_) != OK) {
57 return nullptr;
58 }
59 } else {
60 if (HapParserV2::ParseString(offset, idItem->value_, mMapFile_->mmapLen_, mMapFile_->mmap_) != OK) {
61 return nullptr;
62 }
63 idItem->valueLen_ = idItem->value_.size();
64 }
65 return idItem;
66 }
67
IdValuesV2(ResType resType,uint32_t id,uint32_t offset,const std::string & name)68 IdValuesV2::IdValuesV2(ResType resType, uint32_t id, uint32_t offset, const std::string &name)
69 : resType_(resType), id_(id), offset_(offset), name_(name)
70 {}
71
~IdValuesV2()72 IdValuesV2::~IdValuesV2()
73 {}
74
GetLimitPathsConst() const75 const std::vector<std::shared_ptr<ValueUnderQualifierDir>> &IdValuesV2::GetLimitPathsConst() const
76 {
77 return limitPaths_;
78 }
79
HapResourceV2(const std::string path,time_t lastModTime,bool hasDarkRes)80 HapResourceV2::HapResourceV2(const std::string path, time_t lastModTime, bool hasDarkRes)
81 : HapResource(path, lastModTime)
82 {
83 hasDarkRes_ = hasDarkRes;
84 }
85
~HapResourceV2()86 HapResourceV2::~HapResourceV2()
87 {}
88
IsSystemResource() const89 bool HapResourceV2::IsSystemResource() const
90 {
91 return false;
92 }
93
IsOverlayResource() const94 bool HapResourceV2::IsOverlayResource() const
95 {
96 return false;
97 }
98
GetIdValues(const uint32_t id)99 const std::shared_ptr<IdValues> HapResourceV2::GetIdValues(const uint32_t id)
100 {
101 ReadLock lock(mutex_);
102 if (idMap_.empty()) {
103 RESMGR_HILOGE(RESMGR_TAG, "idMap_ is empty");
104 return nullptr;
105 }
106 std::unordered_map<uint32_t, std::shared_ptr<IdValuesV2>>::const_iterator iter = idMap_.find(id);
107 if (iter == idMap_.end()) {
108 return nullptr;
109 }
110
111 if (!iter->second->IsParsed() && ParseLimitPaths(iter->second) != OK) {
112 return nullptr;
113 }
114 return iter->second;
115 }
116
GetIdValuesByName(const std::string name,const ResType resType)117 const std::shared_ptr<IdValues> HapResourceV2::GetIdValuesByName(
118 const std::string name, const ResType resType)
119 {
120 ReadLock lock(mutex_);
121 if (typeNameMap_.empty()) {
122 RESMGR_HILOGE(RESMGR_TAG, "typeNameMap_ is empty");
123 return nullptr;
124 }
125 std::unordered_map<uint32_t, std::unordered_map<std::string,
126 std::shared_ptr<IdValuesV2>>>::const_iterator mapIterator = typeNameMap_.find(resType);
127 if (mapIterator == typeNameMap_.end()) {
128 return nullptr;
129 }
130 std::unordered_map<std::string, std::shared_ptr<IdValuesV2>>::const_iterator iter = mapIterator->second.find(name);
131 if (iter == mapIterator->second.end()) {
132 return nullptr;
133 }
134
135 if (!iter->second->IsParsed() && ParseLimitPaths(iter->second) != OK) {
136 return nullptr;
137 }
138 return iter->second;
139 }
140
BuildNameTypeIdMapping()141 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> HapResourceV2::BuildNameTypeIdMapping()
142 {
143 ReadLock lock(mutex_);
144 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> result;
145 result.reserve(idMap_.size());
146 for (const auto &item : idMap_) {
147 result[item.second->GetName()][item.second->GetResType()] = item.first;
148 }
149 return result;
150 }
151
GetLocales(std::set<std::string> & outValue,bool includeSystem)152 void HapResourceV2::GetLocales(std::set<std::string> &outValue, bool includeSystem)
153 {
154 ReadLock lock(mutex_);
155 if (keys_.empty()) {
156 RESMGR_HILOGE(RESMGR_TAG, "keys_ is null! GetLocales failed");
157 return;
158 }
159 outValue.insert(locales_.begin(), locales_.end());
160 }
161
Init(std::unordered_map<uint32_t,std::shared_ptr<ResConfigImpl>> & keys,std::unordered_map<uint32_t,std::shared_ptr<IdValuesV2>> & idMap,std::unordered_map<uint32_t,std::unordered_map<std::string,std::shared_ptr<IdValuesV2>>> & typeNameMap,std::shared_ptr<MmapFile> mMapFile)162 bool HapResourceV2::Init(std::unordered_map<uint32_t, std::shared_ptr<ResConfigImpl>> &keys,
163 std::unordered_map<uint32_t, std::shared_ptr<IdValuesV2>> &idMap,
164 std::unordered_map<uint32_t, std::unordered_map<std::string, std::shared_ptr<IdValuesV2>>> &typeNameMap,
165 std::shared_ptr<MmapFile> mMapFile)
166 {
167 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
168 HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
169 #endif
170 #ifdef __WINNT__
171 char separator = '\\';
172 #else
173 char separator = '/';
174 #endif
175 auto index = indexPath_.rfind(separator);
176 if (index == std::string::npos) {
177 RESMGR_HILOGE(RESMGR_TAG, "index path format error");
178 return false;
179 }
180 #if defined(__IDE_PREVIEW__) || defined(__ARKUI_CROSS__)
181 resourcePath_ = indexPath_.substr(0, index + 1);
182 #else
183 if (index < 1) {
184 return false;
185 }
186 index = indexPath_.rfind(separator, index - 1);
187 if (index == std::string::npos) {
188 RESMGR_HILOGE(RESMGR_TAG, "index path format error");
189 return false;
190 }
191 resourcePath_ = indexPath_.substr(0, index + 1);
192 #endif
193
194 keys_ = std::move(keys);
195 idMap_ = std::move(idMap);
196 typeNameMap_ = std::move(typeNameMap);
197 mMapFile_ = mMapFile;
198 return true;
199 }
200
InitThemeSystemRes()201 void HapResourceV2::InitThemeSystemRes()
202 {
203 std::shared_ptr<IdValues> themeSystemRes = nullptr;
204 std::vector<std::shared_ptr<ValueUnderQualifierDir>> configList;
205 themeSystemRes = GetIdValuesByName("system_color_change", ResType::STRING);
206 if (themeSystemRes != nullptr) {
207 std::vector<std::shared_ptr<ValueUnderQualifierDir>> configs = themeSystemRes->GetLimitPathsConst();
208 configList.insert(configList.end(), configs.begin(), configs.end());
209 }
210 themeSystemRes = GetIdValuesByName("system_color_change", ResType::BOOLEAN);
211 if (themeSystemRes != nullptr) {
212 std::vector<std::shared_ptr<ValueUnderQualifierDir>> configs = themeSystemRes->GetLimitPathsConst();
213 configList.insert(configList.end(), configs.begin(), configs.end());
214 }
215
216 for (const auto &cfg : configList) {
217 if (cfg->GetIdItem()->value_ == "true") {
218 isThemeSystemResEnable_ = true;
219 return;
220 }
221 }
222 }
223
ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)224 int32_t HapResourceV2::ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)
225 {
226 std::unique_lock<std::mutex> lock(idValuesMutex_);
227 if (idValue->IsParsed()) {
228 return OK;
229 }
230 ResInfo resInfo;
231 uint32_t offset = idValue->GetOffset();
232 int32_t ret = HapParserV2::ParseResInfo(offset, resInfo, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
233 if (ret != OK) {
234 return ret;
235 }
236 if (resInfo.resId_ != idValue->GetId()) {
237 RESMGR_HILOGE(RESMGR_TAG, "Parse ResInfo failed, ResInfo data error.");
238 return UNKNOWN_ERROR;
239 }
240
241 idValue->ReserveLimitPaths(resInfo.valueCount_);
242 std::pair<std::string, std::string> resPath = std::make_pair(indexPath_, resourcePath_);
243 for (uint32_t i = 0; i < resInfo.valueCount_; i++) {
244 ConfigItem configItem;
245 ret = HapParserV2::ParseConfigItem(offset, configItem, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
246 if (ret != OK) {
247 return ret;
248 }
249
250 std::shared_ptr<ValueUnderQualifierDirV2> vuqd =
251 std::make_shared<ValueUnderQualifierDirV2>(resPath, configItem.offset_, keys_[configItem.resCfgId_]);
252 vuqd->Init(idValue->GetMMap(), idValue->GetResType(), idValue->GetId(), idValue->GetName());
253 idValue->AddLimitPath(vuqd);
254 }
255 idValue->Parse();
256 return OK;
257 }
258
SystemResource()259 SystemResource::SystemResource() : HapResourceV2("", 0)
260 {}
261
SystemResource(const std::string path,time_t lastModTime,bool hasDarkRes)262 SystemResource::SystemResource(const std::string path, time_t lastModTime, bool hasDarkRes)
263 : HapResourceV2(path, lastModTime, hasDarkRes)
264 {}
265
~SystemResource()266 SystemResource::~SystemResource()
267 {}
268
IsSystemResource() const269 bool SystemResource::IsSystemResource() const
270 {
271 return true;
272 }
273
GetLocales(std::set<std::string> & outValue,bool includeSystem)274 void SystemResource::GetLocales(std::set<std::string> &outValue, bool includeSystem)
275 {
276 ReadLock lock(mutex_);
277 if (keys_.empty()) {
278 RESMGR_HILOGE(RESMGR_TAG, "keys_ is null! GetLocales failed");
279 return;
280 }
281 if (!includeSystem) {
282 return;
283 }
284 outValue.insert(locales_.begin(), locales_.end());
285 }
286
ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)287 int32_t SystemResource::ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)
288 {
289 std::unique_lock<std::mutex> lock(idValuesMutex_);
290 if (idValue->IsParsed()) {
291 return OK;
292 }
293 ResInfo resInfo;
294 uint32_t offset = idValue->GetOffset();
295 int32_t ret = HapParserV2::ParseResInfo(offset, resInfo, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
296 if (ret != OK) {
297 return ret;
298 }
299 if (resInfo.resId_ != idValue->GetId()) {
300 RESMGR_HILOGE(RESMGR_TAG, "Parse ResInfo failed, ResInfo data error.");
301 return UNKNOWN_ERROR;
302 }
303
304 idValue->ReserveLimitPaths(resInfo.valueCount_);
305 for (uint32_t i = 0; i < resInfo.valueCount_; i++) {
306 ConfigItem configItem;
307 ret = HapParserV2::ParseConfigItem(offset, configItem, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
308 if (ret != OK) {
309 return ret;
310 }
311
312 std::pair<std::string, std::string> resPath = std::make_pair(indexPath_, resourcePath_);
313 std::shared_ptr<ValueUnderQualifierDirV2> vuqd = std::make_shared<ValueUnderQualifierDirV2>(
314 resPath, configItem.offset_, keys_[configItem.resCfgId_], false, true);
315 vuqd->Init(idValue->GetMMap(), idValue->GetResType(), idValue->GetId(), idValue->GetName());
316 idValue->AddLimitPath(vuqd);
317 }
318 idValue->Parse();
319 return OK;
320 }
321
OverlayResource()322 OverlayResource::OverlayResource() : HapResourceV2("", 0)
323 {}
324
OverlayResource(const std::string path,time_t lastModTime,bool hasDarkRes)325 OverlayResource::OverlayResource(const std::string path, time_t lastModTime, bool hasDarkRes)
326 : HapResourceV2(path, lastModTime, hasDarkRes)
327 {}
328
~OverlayResource()329 OverlayResource::~OverlayResource()
330 {}
331
IsOverlayResource() const332 bool OverlayResource::IsOverlayResource() const
333 {
334 return true;
335 }
336
UpdateOverlayInfo(std::unordered_map<std::string,std::unordered_map<ResType,uint32_t>> & nameTypeId)337 void OverlayResource::UpdateOverlayInfo(
338 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> &nameTypeId)
339 {
340 WriteLock lock(mutex_);
341 std::unordered_map<uint32_t, std::shared_ptr<IdValuesV2>> newIdMap;
342 newIdMap.reserve(idMap_.size());
343 for (auto &item : idMap_) {
344 std::string name = item.second->GetName();
345 ResType type = item.second->GetResType();
346 if (nameTypeId.find(name) == nameTypeId.end() || nameTypeId[name].find(type) == nameTypeId[name].end()) {
347 continue;
348 }
349 uint32_t newId = nameTypeId[name][type];
350 item.second->SetId(newId);
351 newIdMap[newId] = item.second;
352 }
353 idMap_.swap(newIdMap);
354 }
355
GetLocales(std::set<std::string> & outValue,bool includeSystem)356 void OverlayResource::GetLocales(std::set<std::string> &outValue, bool includeSystem)
357 {
358 return;
359 }
360
ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)361 int32_t OverlayResource::ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)
362 {
363 std::unique_lock<std::mutex> lock(idValuesMutex_);
364 if (idValue->IsParsed()) {
365 return OK;
366 }
367 ResInfo resInfo;
368 uint32_t offset = idValue->GetOffset();
369 int32_t ret = HapParserV2::ParseResInfo(offset, resInfo, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
370 if (ret != OK) {
371 return ret;
372 }
373
374 idValue->ReserveLimitPaths(resInfo.valueCount_);
375 for (uint32_t i = 0; i < resInfo.valueCount_; i++) {
376 ConfigItem configItem;
377 ret = HapParserV2::ParseConfigItem(offset, configItem, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
378 if (ret != OK) {
379 return ret;
380 }
381
382 std::pair<std::string, std::string> resPath = std::make_pair(indexPath_, resourcePath_);
383 std::shared_ptr<ValueUnderQualifierDirV2> vuqd = std::make_shared<ValueUnderQualifierDirV2>(
384 resPath, configItem.offset_, keys_[configItem.resCfgId_], true, false);
385 vuqd->Init(idValue->GetMMap(), idValue->GetResType(), idValue->GetId(), idValue->GetName());
386 idValue->AddLimitPath(vuqd);
387 }
388 idValue->Parse();
389 return OK;
390 }
391
SystemOverlayResource(const std::string path,time_t lastModTime,bool hasDarkRes)392 SystemOverlayResource::SystemOverlayResource(const std::string path, time_t lastModTime, bool hasDarkRes)
393 : HapResourceV2(path, lastModTime, hasDarkRes)
394 {}
395
~SystemOverlayResource()396 SystemOverlayResource::~SystemOverlayResource()
397 {}
398
GetLocales(std::set<std::string> & outValue,bool includeSystem)399 void SystemOverlayResource::GetLocales(std::set<std::string> &outValue, bool includeSystem)
400 {
401 SystemResource::GetLocales(outValue, includeSystem);
402 }
403
ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)404 int32_t SystemOverlayResource::ParseLimitPaths(std::shared_ptr<IdValuesV2> idValue)
405 {
406 std::unique_lock<std::mutex> lock(idValuesMutex_);
407 if (idValue->IsParsed()) {
408 return OK;
409 }
410 ResInfo resInfo;
411 uint32_t offset = idValue->GetOffset();
412 int32_t ret = HapParserV2::ParseResInfo(offset, resInfo, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
413 if (ret != OK) {
414 return ret;
415 }
416
417 idValue->ReserveLimitPaths(resInfo.valueCount_);
418 for (uint32_t i = 0; i < resInfo.valueCount_; i++) {
419 ConfigItem configItem;
420 ret = HapParserV2::ParseConfigItem(offset, configItem, idValue->GetMMap()->mmapLen_, idValue->GetMMap()->mmap_);
421 if (ret != OK) {
422 return ret;
423 }
424
425 std::pair<std::string, std::string> resPath = std::make_pair(indexPath_, resourcePath_);
426 std::shared_ptr<ValueUnderQualifierDirV2> vuqd = std::make_shared<ValueUnderQualifierDirV2>(
427 resPath, configItem.offset_, keys_[configItem.resCfgId_], true, true);
428 vuqd->Init(idValue->GetMMap(), idValue->GetResType(), idValue->GetId(), idValue->GetName());
429 idValue->AddLimitPath(vuqd);
430 }
431 idValue->Parse();
432 return OK;
433 }
434 }
435 }
436 }