• 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_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 }