1 /* 2 * Copyright (c) 2021-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_IMAGE_IMAGE_CACHE_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_IMAGE_CACHE_H 18 19 #include <algorithm> 20 #include <list> 21 #include <mutex> 22 #include <shared_mutex> 23 #include <unordered_map> 24 #include <utility> 25 #include <vector> 26 27 #include "base/image/pixel_map.h" 28 #include "base/log/log.h" 29 #include "base/memory/ace_type.h" 30 #include "base/utils/macros.h" 31 32 namespace OHOS::Ace { 33 34 struct CachedImage; 35 class ImageObject; 36 37 namespace NG { 38 struct CachedImage; 39 class ImageObject; 40 } // namespace NG 41 42 template<typename T> 43 struct CacheNode { CacheNodeCacheNode44 CacheNode(std::string key, const T& obj) : cacheKey(std::move(key)), cacheObj(obj) {} 45 std::string cacheKey; 46 T cacheObj; 47 }; 48 49 struct CachedImageData : public AceType { 50 DECLARE_ACE_TYPE(CachedImageData, AceType); 51 52 public: 53 CachedImageData() = default; 54 virtual ~CachedImageData() = default; 55 virtual size_t GetSize() = 0; 56 virtual const uint8_t* GetData() = 0; 57 }; 58 59 struct CacheImageDataNode { CacheImageDataNodeCacheImageDataNode60 CacheImageDataNode(const std::string& key, const RefPtr<CachedImageData>& imageData) 61 : imageDataKey(key), imageDataPtr(imageData) 62 {} 63 std::string imageDataKey; 64 RefPtr<CachedImageData> imageDataPtr; 65 }; 66 67 struct FileInfo { FileInfoFileInfo68 FileInfo(std::string path, size_t size, time_t time) : filePath(std::move(path)), fileSize(size), accessTime(time) 69 {} 70 71 // file information will be sort by access time. 72 bool operator<(const FileInfo& otherFile) const 73 { 74 return accessTime < otherFile.accessTime; 75 } 76 std::string filePath; 77 size_t fileSize; 78 time_t accessTime; 79 }; 80 81 class ACE_EXPORT ImageCache : public AceType { 82 DECLARE_ACE_TYPE(ImageCache, AceType); 83 84 public: 85 static RefPtr<ImageCache> Create(); 86 ImageCache() = default; 87 ~ImageCache() override = default; 88 89 void CacheImage(const std::string& key, const std::shared_ptr<CachedImage>& image); 90 void CacheImageNG(const std::string& key, const std::shared_ptr<NG::CachedImage>& image); 91 std::shared_ptr<CachedImage> GetCacheImage(const std::string& key); 92 std::shared_ptr<NG::CachedImage> GetCacheImageNG(const std::string& key); 93 94 void CacheImageData(const std::string& key, const RefPtr<CachedImageData>& imageData); 95 RefPtr<CachedImageData> GetCacheImageData(const std::string& key); 96 97 // cache interface for [NG::ImageObject] 98 RefPtr<NG::ImageObject> GetCacheImgObjNG(const std::string& key); 99 void CacheImgObjNG(const std::string& key, const RefPtr<NG::ImageObject>& imgObj); 100 101 void CacheImgObj(const std::string& key, const RefPtr<ImageObject>& imgObj); 102 RefPtr<ImageObject> GetCacheImgObj(const std::string& key); 103 104 static void SetCacheFileInfo(); 105 static void WriteCacheFile( 106 const std::string& url, const void* data, size_t size, const std::string& suffix = std::string()); 107 SetCapacity(size_t capacity)108 void SetCapacity(size_t capacity) 109 { 110 LOGI("Set Capacity : %{public}d", static_cast<int32_t>(capacity)); 111 capacity_ = capacity; 112 } 113 SetDataCacheLimit(size_t sizeLimit)114 void SetDataCacheLimit(size_t sizeLimit) 115 { 116 LOGI("Set data size cache limit : %{public}d", static_cast<int32_t>(sizeLimit)); 117 dataSizeLimit_ = sizeLimit; 118 } 119 GetCapacity()120 size_t GetCapacity() const 121 { 122 return capacity_; 123 } 124 GetCachedImageCount()125 size_t GetCachedImageCount() const 126 { 127 std::lock_guard<std::mutex> lock(imageCacheMutex_); 128 return cacheList_.size(); 129 } 130 SetImageCacheFilePath(const std::string & cacheFilePath)131 static void SetImageCacheFilePath(const std::string& cacheFilePath) 132 { 133 std::unique_lock<std::shared_mutex> lock(cacheFilePathMutex_); 134 if (cacheFilePath_.empty()) { 135 cacheFilePath_ = cacheFilePath; 136 } 137 } 138 GetImageCacheFilePath()139 static std::string GetImageCacheFilePath() 140 { 141 std::shared_lock<std::shared_mutex> lock(cacheFilePathMutex_); 142 return cacheFilePath_; 143 } 144 GetImageCacheFilePath(const std::string & url)145 static std::string GetImageCacheFilePath(const std::string& url) 146 { 147 std::shared_lock<std::shared_mutex> lock(cacheFilePathMutex_); 148 #if !defined(PREVIEW) 149 return cacheFilePath_ + "/" + std::to_string(std::hash<std::string> {}(url)); 150 #elif defined(MAC_PLATFORM) || defined(LINUX_PLATFORM) 151 return "/tmp/" + std::to_string(std::hash<std::string> {}(url)); 152 #elif defined(WINDOWS_PLATFORM) 153 char* pathvar; 154 pathvar = getenv("TEMP"); 155 if (!pathvar) { 156 return std::string("C:\\Windows\\Temp") + "\\" + std::to_string(std::hash<std::string> {}(url)); 157 } 158 return std::string(pathvar) + "\\" + std::to_string(std::hash<std::string> {}(url)); 159 #endif 160 } 161 SetCacheFileLimit(size_t cacheFileLimit)162 static void SetCacheFileLimit(size_t cacheFileLimit) 163 { 164 LOGI("Set file cache limit size : %{public}d", static_cast<int32_t>(cacheFileLimit)); 165 cacheFileLimit_ = cacheFileLimit; 166 } 167 SetClearCacheFileRatio(float clearRatio)168 static void SetClearCacheFileRatio(float clearRatio) 169 { 170 // clearRatio must in (0, 1]. 171 if (clearRatio < 0) { 172 clearRatio = 0.1f; 173 } else if (clearRatio > 1) { 174 clearRatio = 1.0f; 175 } 176 clearCacheFileRatio_ = clearRatio; 177 } 178 179 static bool GetFromCacheFile(const std::string& filePath); 180 181 virtual void Clear() = 0; 182 183 virtual RefPtr<CachedImageData> GetDataFromCacheFile(const std::string& filePath) = 0; 184 185 static void Purge(); 186 187 protected: 188 static void ClearCacheFile(const std::vector<std::string>& removeFiles); 189 190 template<typename T> 191 static void CacheWithCountLimitLRU(const std::string& key, const T& cacheObj, std::list<CacheNode<T>>& cacheList, 192 std::unordered_map<std::string, typename std::list<CacheNode<T>>::iterator>& cache, 193 const std::atomic<size_t>& capacity); 194 195 template<typename T> 196 static T GetCacheObjWithCountLimitLRU(const std::string& key, std::list<CacheNode<T>>& cacheList, 197 std::unordered_map<std::string, typename std::list<CacheNode<T>>::iterator>& cache); 198 199 static bool GetFromCacheFileInner(const std::string& filePath); 200 201 bool ProcessImageDataCacheInner(size_t dataSize); 202 203 mutable std::mutex imageCacheMutex_; 204 std::list<CacheNode<std::shared_ptr<CachedImage>>> cacheList_; 205 std::list<CacheNode<std::shared_ptr<NG::CachedImage>>> cacheListNG_; 206 207 std::unordered_map<std::string, std::list<CacheNode<std::shared_ptr<CachedImage>>>::iterator> imageCache_; 208 std::unordered_map<std::string, std::list<CacheNode<std::shared_ptr<NG::CachedImage>>>::iterator> imageCacheNG_; 209 210 std::atomic<size_t> capacity_ = 0; // by default memory cache can store 0 images. 211 212 mutable std::mutex dataCacheListMutex_; 213 std::list<CacheImageDataNode> dataCacheList_; 214 215 std::mutex imageDataCacheMutex_; 216 std::unordered_map<std::string, std::list<CacheImageDataNode>::iterator> imageDataCache_; 217 218 std::atomic<size_t> dataSizeLimit_ = 0; // by default, image data before decoded cache is 0 MB.; 219 std::atomic<size_t> curDataSize_ = 0; 220 221 std::mutex cacheImgObjListMutex_; 222 std::list<CacheNode<RefPtr<ImageObject>>> cacheImgObjList_; 223 std::mutex imgObjCacheMutex_; 224 std::unordered_map<std::string, std::list<CacheNode<RefPtr<ImageObject>>>::iterator> imgObjCache_; 225 std::atomic<size_t> imgObjCapacity_ = 2000; // imgObj is cached after clear image data. 226 227 std::list<CacheNode<RefPtr<NG::ImageObject>>> cacheImgObjListNG_; 228 std::unordered_map<std::string, std::list<CacheNode<RefPtr<NG::ImageObject>>>::iterator> imgObjCacheNG_; 229 230 static std::shared_mutex cacheFilePathMutex_; 231 static std::string cacheFilePath_; 232 233 static std::atomic<size_t> cacheFileLimit_; 234 235 static std::atomic<float> clearCacheFileRatio_; 236 237 static std::mutex cacheFileSizeMutex_; 238 static int32_t cacheFileSize_; 239 240 static std::mutex cacheFileInfoMutex_; 241 static std::list<FileInfo> cacheFileInfo_; 242 static bool hasSetCacheFileInfo_; 243 }; 244 245 struct PixmapCachedData : public CachedImageData { 246 DECLARE_ACE_TYPE(PixmapCachedData, CachedImageData); 247 248 public: PixmapCachedDataPixmapCachedData249 explicit PixmapCachedData(const RefPtr<PixelMap>& data) : pixmap_(data) {} 250 ~PixmapCachedData() override = default; 251 GetSizePixmapCachedData252 size_t GetSize() override 253 { 254 return pixmap_ ? pixmap_->GetByteCount() : 0; 255 } 256 GetDataPixmapCachedData257 const uint8_t* GetData() override 258 { 259 return pixmap_ ? pixmap_->GetPixels() : nullptr; 260 } 261 262 const RefPtr<PixelMap> pixmap_; 263 }; 264 265 } // namespace OHOS::Ace 266 267 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_IMAGE_CACHE_H 268