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