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