• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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