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