• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_RESOURCE_RESOURCE_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_RESOURCE_RESOURCE_MANAGER_H
18 
19 #include <climits>
20 #include <functional>
21 #include <map>
22 #include <mutex>
23 #include <shared_mutex>
24 #include <string>
25 #include <utility>
26 
27 #include "base/memory/ace_type.h"
28 #include "base/memory/referenced.h"
29 #include "base/utils/string_utils.h"
30 #include "base/utils/resource_configuration.h"
31 #include "core/common/resource/resource_object.h"
32 #include "core/components/theme/resource_adapter.h"
33 #include "core/common/lru/count_limit_lru.h"
34 
35 namespace OHOS::Ace {
36 
37 struct ResourceErrorInfo {
ResourceErrorInfoResourceErrorInfo38     ResourceErrorInfo(int32_t nodeId, std::string sourceKey, std::string sourceTag, std::string nodeTag,
39         int64_t errorTime, int32_t state)
40         : nodeId(nodeId), sourceKey(std::move(sourceKey)), sourceTag(std::move(sourceTag)),
41           nodeTag(std::move(nodeTag)), errorTime(errorTime), state(state) {}
42     int32_t nodeId;
43     std::string sourceKey;
44     std::string sourceTag;
45     std::string nodeTag;
46     int64_t errorTime;
47     int32_t state;
48 };
49 
50 class ACE_FORCE_EXPORT ResourceManager final : public AceType {
51     DECLARE_ACE_TYPE(ResourceManager, AceType);
52 
53 public:
54     ~ResourceManager() = default;
55 
56     static ResourceManager& GetInstance();
57 
58     RefPtr<ResourceAdapter> GetOrCreateResourceAdapter(const RefPtr<ResourceObject>& resourceObject);
59 
MakeCacheKey(const std::string & bundleName,const std::string & moduleName,int32_t instanceId)60     std::string MakeCacheKey(const std::string& bundleName, const std::string& moduleName, int32_t instanceId)
61     {
62         if (bundleName.empty() && moduleName.empty()) {
63             return std::to_string(instanceId);
64         }
65         return bundleName + "." + moduleName + "." + std::to_string(instanceId);
66     }
67 
68     void AddResourceAdapter(const std::string& bundleName, const std::string& moduleName, int32_t instanceId,
69         RefPtr<ResourceAdapter>& resourceAdapter, bool replace = false)
70     {
71         std::unique_lock<std::shared_mutex> lock(mutex_);
72         if (bundleName.empty() && moduleName.empty()) {
73             resourceAdapters_[std::to_string(instanceId)] = resourceAdapter;
74         } else {
75             auto key = MakeCacheKey(bundleName, moduleName, instanceId);
76             if (replace) {
77                 CountLimitLRU::RemoveCacheObjFromCountLimitLRU<RefPtr<ResourceAdapter>>(key, cacheList_, cache_);
78             }
79             CountLimitLRU::CacheWithCountLimitLRU<RefPtr<ResourceAdapter>>(
80                 key, resourceAdapter, cacheList_, cache_, capacity_);
81         }
82     }
83 
UpdateMainResourceAdapter(const std::string & bundleName,const std::string & moduleName,int32_t instanceId,RefPtr<ResourceAdapter> & resourceAdapter)84     void UpdateMainResourceAdapter(const std::string& bundleName, const std::string& moduleName, int32_t instanceId,
85         RefPtr<ResourceAdapter>& resourceAdapter)
86     {
87         std::unique_lock<std::shared_mutex> lock(mutex_);
88         auto defaultKey = MakeCacheKey("", "", instanceId);
89         auto key = MakeCacheKey(bundleName, moduleName, instanceId);
90         resourceAdapters_[key] = resourceAdapter;
91         resourceAdapters_[defaultKey] = resourceAdapter;
92     }
93 
IsResourceAdapterRecord(const std::string & bundleName,const std::string & moduleName,int32_t instanceId)94     bool IsResourceAdapterRecord(const std::string& bundleName, const std::string& moduleName, int32_t instanceId)
95     {
96         std::shared_lock<std::shared_mutex> lock(mutex_);
97         auto key = MakeCacheKey(bundleName, moduleName, instanceId);
98         if (resourceAdapters_.find(key) != resourceAdapters_.end()) {
99             return true;
100         }
101         return cache_.find(key) != cache_.end();
102     }
103 
GetCacheKeyInstanceId(const std::string & key)104     std::string GetCacheKeyInstanceId(const std::string& key)
105     {
106         std::vector<std::string> splitter;
107         StringUtils::StringSplitter(key, '.', splitter);
108         return splitter.back();
109     }
110 
GetResourceAdapter(const std::string & bundleName,const std::string & moduleName,int32_t instanceId)111     RefPtr<ResourceAdapter> GetResourceAdapter(
112         const std::string& bundleName, const std::string& moduleName, int32_t instanceId)
113     {
114         std::unique_lock<std::shared_mutex> lock(mutex_);
115         auto key = MakeCacheKey(bundleName, moduleName, instanceId);
116         auto mapIter = resourceAdapters_.find(key);
117         if (mapIter != resourceAdapters_.end()) {
118             if (instanceId == -1) {
119                 TAG_LOGW(AceLogTag::ACE_RESOURCE, "Get resourceAdapter without UI!");
120             }
121             return mapIter->second;
122         } else if (bundleName.empty() && moduleName.empty()) {
123             TAG_LOGW(AceLogTag::ACE_RESOURCE,
124                 "Get default resourceAdapter %{public}d failed, don't get resource while UIContent not initialized yet",
125                 instanceId);
126             return ResourceAdapter::Create();
127         }
128 
129         auto resAdapter = CountLimitLRU::GetCacheObjWithCountLimitLRU<RefPtr<ResourceAdapter>>(key, cacheList_, cache_);
130         if (resAdapter != nullptr) {
131             return resAdapter;
132         }
133 
134         return nullptr;
135     }
136 
GetResourceAdapter(int32_t instanceId)137     RefPtr<ResourceAdapter> GetResourceAdapter(int32_t instanceId)
138     {
139         std::shared_lock<std::shared_mutex> lock(mutex_);
140         auto key = MakeCacheKey("", "", instanceId);
141         if (resourceAdapters_.find(key) != resourceAdapters_.end()) {
142             return resourceAdapters_.at(key);
143         }
144         return nullptr;
145     }
146 
147     void UpdateResourceConfig(const std::string& /*bundleName*/, const std::string& /*moduleName*/, int32_t instanceId,
148         const ResourceConfiguration& config, bool themeFlag = false);
149 
RemoveResourceAdapter(const std::string & bundleName,const std::string & moduleName,int32_t instanceId)150     void RemoveResourceAdapter(const std::string& bundleName, const std::string& moduleName, int32_t instanceId)
151     {
152         std::unique_lock<std::shared_mutex> lock(mutex_);
153         std::string key = MakeCacheKey(bundleName, moduleName, instanceId);
154         if (resourceAdapters_.find(key) != resourceAdapters_.end()) {
155             resourceAdapters_.erase(key);
156         }
157         if (!bundleName.empty() && !moduleName.empty()) {
158             CountLimitLRU::RemoveCacheObjFromCountLimitLRU<RefPtr<ResourceAdapter>>(key, cacheList_, cache_);
159         }
160     }
161 
Reset()162     void Reset()
163     {
164         std::unique_lock<std::shared_mutex> lock(mutex_);
165         cacheList_.clear();
166         cache_.clear();
167         TAG_LOGI(AceLogTag::ACE_RESOURCE, "The cache of Resource has been released!");
168     }
169 
170     void UpdateColorMode(
171         const std::string& /*bundleName*/, const std::string& /*moduleName*/, int32_t instanceId, ColorMode colorMode);
172 
173     void RegisterMainResourceAdapter(const std::string& bundleName, const std::string& moduleName, int32_t instanceId,
174         const RefPtr<ResourceAdapter>& resAdapter);
175 
176     void DumpResLoadError();
177 
AddResourceLoadError(ResourceErrorInfo errorInfo)178     void AddResourceLoadError(ResourceErrorInfo errorInfo)
179     {
180         std::unique_lock<std::shared_mutex> lock(errorMutex_);
181         resourceErrorList_.emplace_front(errorInfo);
182         if (resourceErrorList_.size() > MAX_DUMP_LIST_SIZE) {
183             resourceErrorList_.pop_back();
184         }
185     }
186 
SetResourceCacheSize(size_t cacheSize)187     void SetResourceCacheSize(size_t cacheSize) {
188         capacity_.store(cacheSize);
189     }
190 
191 private:
192     ResourceManager() = default;
193 
194     static const size_t MAX_DUMP_LIST_SIZE = 100;
195     std::unordered_map<std::string, RefPtr<ResourceAdapter>> resourceAdapters_;
196     std::shared_mutex mutex_;
197 
198     std::atomic<size_t> capacity_ = 3;
199     std::list<CacheNode<RefPtr<ResourceAdapter>>> cacheList_;
200     std::unordered_map<std::string, std::list<CacheNode<RefPtr<ResourceAdapter>>>::iterator> cache_;
201     std::shared_mutex errorMutex_;
202     std::list<ResourceErrorInfo> resourceErrorList_;
203 };
204 } // namespace OHOS::Ace
205 
206 #endif