• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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