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