1 /*
2 * Copyright (c) 2024-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_manager.h"
17
18 #include <sys/stat.h>
19 #include "hap_parser.h"
20 #include "hap_parser_v1.h"
21 #include "hap_parser_v2.h"
22 #include "hilog_wrapper.h"
23 #include "utils/errors.h"
24 #include "utils/utils.h"
25
26 #if defined(__WINNT__)
27 #include <cstring>
28 #else
29 #include "securec.h"
30 #endif
31
32 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
33 #include "hitrace_meter.h"
34 #endif
35
36 namespace OHOS {
37 namespace Global {
38 namespace Resource {
GetInstance()39 HapResourceManager& HapResourceManager::GetInstance()
40 {
41 static HapResourceManager instance;
42 return instance;
43 }
44
IsNewModule(const char * path)45 bool IsNewModule(const char *path)
46 {
47 std::unique_ptr<uint8_t[]> buffer = nullptr;
48 size_t bufLen = 0;
49 if (!HapParser::GetIndexData(path, buffer, bufLen)) {
50 return false;
51 }
52 if (ResHeader::RES_HEADER_LEN > bufLen) {
53 return false;
54 }
55
56 ResHeader resHeader;
57 errno_t eret = memcpy_s(&resHeader, sizeof(ResHeader), buffer.get(), ResHeader::RES_HEADER_LEN);
58 if (eret != OK) {
59 return false;
60 }
61
62 std::string version = std::string(resHeader.version_);
63 if (version.substr(0, version.find(" ")) == "Restool") {
64 return false;
65 }
66 return true;
67 }
68
Load(const char * path,std::shared_ptr<ResConfigImpl> & defaultConfig,bool isSystem,bool isOverlay,uint32_t selectedTypes)69 const std::shared_ptr<HapResource> HapResourceManager::Load(const char *path,
70 std::shared_ptr<ResConfigImpl> &defaultConfig, bool isSystem, bool isOverlay, uint32_t selectedTypes)
71 {
72 std::shared_ptr<HapResource> pResource = nullptr;
73 struct stat fileStat {};
74 int ret = stat(path, &fileStat);
75 if (ret != 0) {
76 fileStat.st_mtime = 0;
77 }
78 if (selectedTypes == SELECT_ALL) {
79 pResource = this->GetHapResource(path);
80 if (pResource != nullptr && ret == 0 && fileStat.st_mtime == pResource->GetLastModTime()) {
81 pResource->Update(defaultConfig);
82 return pResource;
83 }
84 }
85
86 std::unique_ptr<HapParser> hapParser = nullptr;
87 bool isNewModule = IsNewModule(path);
88 if (isNewModule) {
89 hapParser = std::make_unique<HapParserV2>();
90 } else {
91 hapParser = std::make_unique<HapParserV1>(defaultConfig, selectedTypes, isSystem || isOverlay);
92 }
93 if (hapParser == nullptr || !hapParser->Init(path)) {
94 if (path == nullptr || std::string(path).empty()) {
95 RESMGR_HILOGE(RESMGR_TAG, "empty path, module:%{public}d", isNewModule);
96 }
97 return nullptr;
98 }
99
100 pResource = hapParser->GetHapResource(path, isSystem, isOverlay);
101 if (pResource == nullptr) {
102 return nullptr;
103 }
104
105 if (selectedTypes == SELECT_ALL) {
106 pResource->SetLastModTime(fileStat.st_mtime);
107 pResource = this->PutAndGetResource(path, pResource);
108 }
109 pResource->Update(defaultConfig);
110 return pResource;
111 }
112
LoadOverlays(const std::string & path,const std::vector<std::string> & overlayPaths,std::shared_ptr<ResConfigImpl> & defaultConfig,bool isSystem)113 const std::unordered_map<std::string, std::shared_ptr<HapResource>> HapResourceManager::LoadOverlays(
114 const std::string &path, const std::vector<std::string> &overlayPaths,
115 std::shared_ptr<ResConfigImpl> &defaultConfig, bool isSystem)
116 {
117 std::unordered_map<std::string, std::shared_ptr<HapResource>> result;
118 do {
119 const std::shared_ptr<HapResource> targetResource = this->Load(path.c_str(), defaultConfig, isSystem);
120 if (targetResource == nullptr) {
121 RESMGR_HILOGE(RESMGR_TAG, "load target failed");
122 break;
123 }
124 result[path] = targetResource;
125 bool success = true;
126 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> mapping =
127 targetResource->BuildNameTypeIdMapping();
128 for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
129 // load overlay hap, the isOverlay flag set true.
130 const std::shared_ptr<HapResource> overlayResource =
131 this->Load(iter->c_str(), defaultConfig, isSystem, true);
132 if (overlayResource == nullptr) {
133 success = false;
134 break;
135 }
136 result[*iter] = overlayResource;
137 }
138
139 if (!success) {
140 RESMGR_HILOGE(RESMGR_TAG, "load overlay failed");
141 break;
142 }
143
144 for (auto iter = result.begin(); iter != result.end(); iter++) {
145 auto index = iter->first.find(path);
146 if (index == std::string::npos) {
147 iter->second->UpdateOverlayInfo(mapping);
148 }
149 }
150 return result;
151 } while (false);
152
153 result.clear();
154 return std::unordered_map<std::string, std::shared_ptr<HapResource>>();
155 }
156
PutAndGetResource(const std::string & path,std::shared_ptr<HapResource> pResource)157 std::shared_ptr<HapResource> HapResourceManager::PutAndGetResource(const std::string &path,
158 std::shared_ptr<HapResource> pResource)
159 {
160 std::unique_lock<std::shared_mutex> lock(mutexRw_);
161 auto iter = hapResourceMap_.find(path);
162 if (iter != hapResourceMap_.end()) {
163 auto res = iter->second.lock();
164 if (res != nullptr && res->GetLastModTime() == pResource->GetLastModTime()) {
165 return res;
166 }
167 }
168 hapResourceMap_[path] = pResource;
169 return pResource;
170 }
171
PutPatchResource(const std::string & path,const std::string & patchPath)172 bool HapResourceManager::PutPatchResource(const std::string &path, const std::string &patchPath)
173 {
174 std::unique_lock<std::shared_mutex> lock(mutexRw_);
175 if (hapResourceMap_.find(path) != hapResourceMap_.end()) {
176 std::shared_ptr<HapResource> pResource = hapResourceMap_[path].lock();
177 if (pResource) {
178 pResource->SetPatchPath(patchPath);
179 pResource->SetHasPatch(true);
180 return true;
181 }
182 }
183 return false;
184 }
185
GetHapResource(const std::string & path)186 std::shared_ptr<HapResource> HapResourceManager::GetHapResource(const std::string &path)
187 {
188 std::shared_lock<std::shared_mutex> lock(mutexRw_);
189 auto iter = hapResourceMap_.find(path);
190 if (iter != hapResourceMap_.end()) {
191 return iter->second.lock();
192 }
193 return nullptr;
194 }
195
196 #if defined(__ARKUI_CROSS__)
RemoveHapResource(const std::string & path)197 void HapResourceManager::RemoveHapResource(const std::string &path)
198 {
199 std::unique_lock<std::shared_mutex> lock(mutexRw_);
200 auto iter = hapResourceMap_.find(path);
201 if (iter != hapResourceMap_.end()) {
202 hapResourceMap_.erase(iter);
203 }
204 }
205 #endif
206 } // namespace Resource
207 } // namespace Global
208 } // namespace OHOS