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