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