1 /*
2 * Copyright (C) 2024 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 #define MLOG_TAG "PictureDataOperations"
17
18 #include "picture_data_operations.h"
19 #include "file_utils.h"
20 #include "media_log.h"
21 #include "parameter.h"
22 #include "parameters.h"
23
24 using namespace std;
25 namespace OHOS {
26 namespace Media {
27 int32_t PictureDataOperations::taskSize = 0;
28 const int32_t SAVE_PICTURE_TIMEOUT_SEC = 20;
29
PictureDataOperations()30 PictureDataOperations::PictureDataOperations()
31 {
32 max_capibilty = stoi(system::GetParameter("const.multimedia.max_picture_capbility", "3")); // MAX_PICTURE_CAPBILITY
33 }
34
~PictureDataOperations()35 PictureDataOperations::~PictureDataOperations()
36 {
37 lowQualityPictureMap_.clear();
38 highQualityPictureMap_.clear();
39 highQualityPictureImageId.clear();
40 }
41
CleanPictureMapData(std::map<std::string,sptr<PicturePair>> & pictureMap,PictureType pictureType)42 void PictureDataOperations::CleanPictureMapData(std::map<std::string, sptr<PicturePair>>& pictureMap,
43 PictureType pictureType)
44 {
45 auto iter = pictureMap.begin();
46 while (iter != pictureMap.end()) {
47 time_t now = time(nullptr);
48 bool isNeedDeletePicture = ((iter->second)->expireTime_ < now) && ((iter->second)->isCleanImmediately_);
49 if (isNeedDeletePicture || ((iter->second)->expireTime_ + SAVE_PICTURE_TIMEOUT_SEC) < now) {
50 if (pictureType == LOW_QUALITY_PICTURE) {
51 FileUtils::SavePicture(iter->first, (iter->second)->picture_, false, true);
52 }
53 MEDIA_INFO_LOG("enter CleanDateByPictureMap %{public}s enter", (iter->first).c_str());
54 iter->second = nullptr;
55 iter = pictureMap.erase(iter);
56 } else {
57 iter++;
58 }
59 }
60 }
61
CleanDateForPeriodical()62 void PictureDataOperations::CleanDateForPeriodical()
63 {
64 lock_guard<mutex> lock(pictureMapMutex_);
65 enum PictureType pictureType;
66 for (pictureType = LOW_QUALITY_PICTURE; pictureType <= HIGH_QUALITY_PICTURE;
67 pictureType = (PictureType)(pictureType + 1)) {
68 switch (pictureType) {
69 case LOW_QUALITY_PICTURE:
70 CleanPictureMapData(lowQualityPictureMap_, pictureType);
71 break;
72 case HIGH_QUALITY_PICTURE:
73 CleanPictureMapData(highQualityPictureMap_, pictureType);
74 break;
75 default:
76 break;
77 }
78 }
79 }
80
InsertPictureData(const std::string & imageId,sptr<PicturePair> & picturePair,PictureType pictureType)81 void PictureDataOperations::InsertPictureData(const std::string& imageId, sptr<PicturePair>& picturePair,
82 PictureType pictureType)
83 {
84 MEDIA_INFO_LOG("enter InsertPictureData %{public}s enter", imageId.c_str());
85 switch (pictureType) {
86 case LOW_QUALITY_PICTURE:{
87 lock_guard<mutex> lock(pictureMapMutex_);
88 auto iter = lowQualityPictureMap_.find(imageId);
89 if (iter != lowQualityPictureMap_.end()) {
90 iter->second = nullptr;
91 lowQualityPictureMap_.erase(iter);
92 }
93 lowQualityPictureMap_[imageId] = picturePair;
94 }
95 break;
96 case HIGH_QUALITY_PICTURE:
97 if (highQualityPictureMap_.find(imageId) == highQualityPictureMap_.end()) {
98 highQualityPictureImageId.push_back(imageId);
99 }
100 CleanHighQualityPictureDataInternal(imageId, picturePair, highQualityPictureImageId);
101 break;
102 default:
103 break;
104 }
105
106 MEDIA_DEBUG_LOG("end InsertPictureData");
107 }
108
CleanHighQualityPictureDataInternal(const std::string & imageId,sptr<PicturePair> & picturePair,std::list<std::string> & pictureImageIdList)109 void PictureDataOperations::CleanHighQualityPictureDataInternal(const std::string& imageId,
110 sptr<PicturePair>& picturePair,
111 std::list<std::string>& pictureImageIdList)
112 {
113 MEDIA_DEBUG_LOG("enter %{public}zu", highQualityPictureMap_.size());
114 lock_guard<mutex> lock(pictureMapMutex_);
115 // 清理低质量图
116 auto iterPicture = lowQualityPictureMap_.find(imageId);
117 if (iterPicture != lowQualityPictureMap_.end()) {
118 iterPicture->second = nullptr;
119 lowQualityPictureMap_.erase(iterPicture);
120 }
121 // 存储高质量图
122 iterPicture = highQualityPictureMap_.find(imageId);
123 if (iterPicture != highQualityPictureMap_.end()) {
124 iterPicture->second = nullptr;
125 highQualityPictureMap_.erase(iterPicture);
126 }
127 highQualityPictureMap_[imageId] = picturePair;
128
129 // 删除至最大值,高质量不用落盘
130 for (auto iter = pictureImageIdList.begin(); iter != pictureImageIdList.end();) {
131 if ((int)(highQualityPictureMap_.size()) <= max_capibilty) {
132 return;
133 }
134 std::string imageId = *iter;
135 std::map<std::string, sptr<PicturePair>>::iterator iterPicture = highQualityPictureMap_.find(imageId);
136 if (iterPicture != highQualityPictureMap_.end() && (iterPicture->second)->isCleanImmediately_) {
137 iterPicture->second = nullptr;
138 highQualityPictureMap_.erase(iterPicture);
139 iter = pictureImageIdList.erase(iter);
140 } else {
141 iter++;
142 }
143 }
144 MEDIA_DEBUG_LOG("end");
145 }
146
GetDataWithImageId(const std::string & imageId,bool & isHighQualityPicture,bool isCleanImmediately)147 std::shared_ptr<Media::Picture> PictureDataOperations::GetDataWithImageId(const std::string& imageId,
148 bool &isHighQualityPicture, bool isCleanImmediately)
149 {
150 MEDIA_DEBUG_LOG("enter %{public}s enter", imageId.c_str());
151 enum PictureType pictureType;
152 std::shared_ptr<Media::Picture> picture;
153 isHighQualityPicture = false;
154 for (pictureType = HIGH_QUALITY_PICTURE; pictureType >= LOW_QUALITY_PICTURE;
155 pictureType = (PictureType)(pictureType - 1)) {
156 picture = GetDataWithImageIdAndPictureType(imageId, pictureType, isCleanImmediately);
157 if (picture != nullptr && picture->GetMainPixel() != nullptr) {
158 MEDIA_DEBUG_LOG("GetDataWithImageId is not null ");
159 isHighQualityPicture = (pictureType == HIGH_QUALITY_PICTURE);
160 return picture;
161 } else {
162 MEDIA_DEBUG_LOG("GetDataWithImageId is not found ");
163 }
164 }
165 return picture;
166 }
167
168
SavePictureWithImageId(const std::string & imageId)169 void PictureDataOperations::SavePictureWithImageId(const std::string& imageId)
170 {
171 MEDIA_DEBUG_LOG("enter ");
172 enum PictureType pictureType;
173 bool isSuccess = false;
174 for (pictureType = HIGH_QUALITY_PICTURE; pictureType >= LOW_QUALITY_PICTURE;
175 pictureType = (PictureType)(pictureType - 1)) {
176 switch (pictureType) {
177 case LOW_QUALITY_PICTURE:
178 isSuccess = SavePicture(imageId, lowQualityPictureMap_, true);
179 break;
180 case HIGH_QUALITY_PICTURE:
181 isSuccess = SavePicture(imageId, highQualityPictureMap_, false);
182 break;
183 default:
184 break;
185 }
186 }
187 if (isSuccess) { // 高质量提前返回
188 return;
189 }
190 MEDIA_DEBUG_LOG("end ");
191 }
192
GetDataWithImageIdAndPictureType(const std::string & imageId,PictureType pictureType,bool isCleanImmediately)193 std::shared_ptr<Media::Picture> PictureDataOperations::GetDataWithImageIdAndPictureType(const std::string& imageId,
194 PictureType pictureType, bool isCleanImmediately)
195 {
196 MEDIA_DEBUG_LOG("enter ");
197 lock_guard<mutex> lock(pictureMapMutex_);
198 std::map<std::string, sptr<PicturePair>>::iterator iter;
199 std::shared_ptr<Media::Picture> picture;
200 switch (pictureType) {
201 case LOW_QUALITY_PICTURE:
202 iter = lowQualityPictureMap_.find(imageId);
203 if (iter != lowQualityPictureMap_.end()) {
204 (iter->second)->isCleanImmediately_ = isCleanImmediately;
205 picture = (iter->second)->picture_;
206 }
207 break;
208 case HIGH_QUALITY_PICTURE:
209 iter = highQualityPictureMap_.find(imageId);
210 if (iter != highQualityPictureMap_.end()) {
211 (iter->second)->isCleanImmediately_ = isCleanImmediately;
212 picture = (iter->second)->picture_;
213 }
214 break;
215 default:
216 break;
217 }
218 return picture;
219 }
220
IsExsitDataForPictureType(PictureType pictureType)221 bool PictureDataOperations::IsExsitDataForPictureType(PictureType pictureType)
222 {
223 MEDIA_DEBUG_LOG("enter ");
224 lock_guard<mutex> lock(pictureMapMutex_);
225 bool isExsit = false;
226 switch (pictureType) {
227 case LOW_QUALITY_PICTURE:
228 isExsit = lowQualityPictureMap_.size() >= 1;
229 break;
230 case HIGH_QUALITY_PICTURE:
231 isExsit = highQualityPictureMap_.size() >= 1;
232 break;
233 default:
234 break;
235 }
236 return isExsit;
237 }
238
IsExsitDataForPictureType(const std::string & imageId,PictureType pictureType)239 bool PictureDataOperations::IsExsitDataForPictureType(const std::string& imageId, PictureType pictureType)
240 {
241 MEDIA_DEBUG_LOG("enter ");
242 lock_guard<mutex> lock(pictureMapMutex_);
243 bool isExsit = false;
244 switch (pictureType) {
245 case LOW_QUALITY_PICTURE:
246 isExsit = lowQualityPictureMap_.size() >= 0 &&
247 lowQualityPictureMap_.find(imageId) != lowQualityPictureMap_.end();
248 break;
249 case HIGH_QUALITY_PICTURE:
250 isExsit = highQualityPictureMap_.size() > 0 &&
251 highQualityPictureMap_.find(imageId) != highQualityPictureMap_.end();
252 break;
253 default:
254 break;
255 }
256 return isExsit;
257 }
258
259 // 落盘低质量图,包括低质量裸图/低质量
SaveLowQualityPicture(const std::string & imageId)260 void PictureDataOperations::SaveLowQualityPicture(const std::string& imageId)
261 {
262 MEDIA_DEBUG_LOG("enter ");
263 enum PictureType pictureType;
264 bool isSuccess = SavePicture(imageId, lowQualityPictureMap_, true);
265 }
266
267 // 落盘低质量图,包括低质量裸图
SavePicture(const std::string & imageId,std::map<std::string,sptr<PicturePair>> & pictureMap,bool isLowQualityPicture)268 bool PictureDataOperations::SavePicture(const std::string& imageId,
269 std::map<std::string, sptr<PicturePair>>& pictureMap, bool isLowQualityPicture)
270 {
271 MEDIA_DEBUG_LOG("enter photoId: %{public}s", imageId.c_str());
272 lock_guard<mutex> lock(pictureMapMutex_);
273 bool isSuccess = false;
274 if (pictureMap.size() == 0) {
275 return false;
276 }
277 std::map<std::string, sptr<PicturePair>>::iterator iter;
278 if (imageId == "default") {
279 iter = pictureMap.begin();
280 } else {
281 iter = pictureMap.find(imageId);
282 }
283 if (iter != pictureMap.end()) {
284 FileUtils::SavePicture(iter->first, (iter->second)->picture_, false, isLowQualityPicture);
285 MEDIA_INFO_LOG("SavePicture, photoId: %{public}s", imageId.c_str());
286 // 落盘后清除缓存数据
287 pictureMap.erase(iter);
288 isSuccess = true;
289 }
290 return isSuccess;
291 }
292
SavePictureExecutor(AsyncTaskData * data)293 void PictureDataOperations::SavePictureExecutor(AsyncTaskData *data)
294 {
295 auto *taskData = static_cast<SavePictureData *>(data);
296 auto picturePair = taskData->picturePair_;
297
298 MEDIA_DEBUG_LOG("SavePictureExecutor %{public}d ", taskSize);
299 FileUtils::SavePicture(picturePair->photoId_, picturePair->picture_, false, true);
300 picturePair->isCleanImmediately_ = true;
301 taskSize --;
302 }
303
AddSavePictureTask(sptr<PicturePair> & picturePair)304 int32_t PictureDataOperations::AddSavePictureTask(sptr<PicturePair>& picturePair)
305 {
306 auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
307 if (asyncWorker == nullptr) {
308 MEDIA_DEBUG_LOG("Failed to get async worker instance!");
309 return -1;
310 }
311
312 auto *taskData = new (std::nothrow) SavePictureData(picturePair);
313 if (taskData == nullptr) {
314 MEDIA_ERR_LOG("Failed to alloc async data for downloading cloud files!");
315 return -1;
316 }
317
318 auto asyncTask = std::make_shared<MediaLibraryAsyncTask>(SavePictureExecutor, taskData);
319 asyncWorker->AddTask(asyncTask, true);
320 taskSize ++;
321 return 0;
322 }
323
GetPendingTaskSize()324 int32_t PictureDataOperations::GetPendingTaskSize()
325 {
326 lock_guard<mutex> lock(pictureMapMutex_);
327 return lowQualityPictureMap_.size() + highQualityPictureMap_.size();
328 }
329
DeleteDataWithImageId(const std::string & imageId,PictureType pictureType)330 void PictureDataOperations::DeleteDataWithImageId(const std::string& imageId, PictureType pictureType)
331 {
332 MEDIA_DEBUG_LOG("enter ");
333 lock_guard<mutex> lock(pictureMapMutex_);
334 MEDIA_INFO_LOG("DeleteDataWithImageId start: %{public}s", imageId.c_str());
335 std::map<std::string, sptr<PicturePair>>::iterator iter;
336 switch (pictureType) {
337 case LOW_QUALITY_PICTURE:
338 iter = lowQualityPictureMap_.find(imageId);
339 if (iter != lowQualityPictureMap_.end()) {
340 (iter->second)->picture_ = nullptr;
341 lowQualityPictureMap_.erase(iter);
342 }
343 break;
344 case HIGH_QUALITY_PICTURE:
345 iter = highQualityPictureMap_.find(imageId);
346 if (iter != highQualityPictureMap_.end()) {
347 (iter->second)->picture_ = nullptr;
348 highQualityPictureMap_.erase(iter);
349 }
350 break;
351 default:
352 break;
353 }
354 MEDIA_DEBUG_LOG("DeleteDataWithImageId end: %{public}s", imageId.c_str());
355 }
356
FinishAccessingPicture(const std::string & imageId,PictureType pictureType)357 void PictureDataOperations::FinishAccessingPicture(const std::string& imageId, PictureType pictureType)
358 {
359 lock_guard<mutex> lock(pictureMapMutex_);
360 MEDIA_INFO_LOG("FinishAccessingPicture start: %{public}s", imageId.c_str());
361 std::map<std::string, sptr<PicturePair>>::iterator iter;
362 switch (pictureType) {
363 case LOW_QUALITY_PICTURE:
364 iter = lowQualityPictureMap_.find(imageId);
365 if (iter != lowQualityPictureMap_.end()) {
366 (iter->second)->isCleanImmediately_ = true;
367 }
368 break;
369 case HIGH_QUALITY_PICTURE:
370 iter = highQualityPictureMap_.find(imageId);
371 if (iter != highQualityPictureMap_.end()) {
372 (iter->second)->isCleanImmediately_ = true;
373 }
374 break;
375 default:
376 break;
377 }
378 MEDIA_DEBUG_LOG("FinishAccessingPicture end: %{public}s", imageId.c_str());
379 }
380 } // namespace Media
381 } // namespace OHOS