• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-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 #define MLOG_TAG "Thumbnail"
16 
17 #include "ithumbnail_helper.h"
18 
19 #include "ability_manager_client.h"
20 #include "background_task_mgr_helper.h"
21 #include "cloud_sync_helper.h"
22 #include "dfx_cloud_manager.h"
23 #include "dfx_utils.h"
24 #include "hitrace_meter.h"
25 #include "ipc_skeleton.h"
26 #include "media_column.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_kvstore_manager.h"
29 #include "medialibrary_notify.h"
30 #include "medialibrary_photo_operations.h"
31 #include "medialibrary_type_const.h"
32 #include "media_file_utils.h"
33 #include "media_log.h"
34 #include "medialibrary_rdbstore.h"
35 #include "medialibrary_unistore_manager.h"
36 #include "post_event_utils.h"
37 #include "post_proc.h"
38 #include "result_set_utils.h"
39 #include "rdb_predicates.h"
40 #include "rdb_helper.h"
41 #include "single_kvstore.h"
42 #include "thumbnail_const.h"
43 #include "thumbnail_generate_worker_manager.h"
44 #include "thumbnail_image_framework_utils.h"
45 #include "thumbnail_source_loading.h"
46 #include "medialibrary_astc_stat.h"
47 using namespace std;
48 using namespace OHOS::DistributedKv;
49 using namespace OHOS::NativeRdb;
50 
51 namespace OHOS {
52 namespace Media {
53 
StoreThumbnailSize(const ThumbRdbOpt & opts,const ThumbnailData & data)54 void StoreThumbnailSize(const ThumbRdbOpt& opts, const ThumbnailData& data)
55 {
56     std::string photoId = opts.row.empty() ? data.id : opts.row;
57     std::string tmpPath = opts.path.empty() ? data.path : opts.path;
58     if (tmpPath.find(ROOT_MEDIA_DIR + PHOTO_BUCKET) != string::npos) {
59         MediaLibraryPhotoOperations::StoreThumbnailSize(photoId, tmpPath);
60     }
61 }
62 
CloudSyncOnGenerationComplete(std::shared_ptr<ThumbnailTaskData> & data)63 void IThumbnailHelper::CloudSyncOnGenerationComplete(std::shared_ptr<ThumbnailTaskData> &data)
64 {
65     CloudSyncHelper::GetInstance()->isThumbnailGenerationCompleted_ = true;
66     CloudSyncHelper::GetInstance()->StartSync();
67     MEDIA_INFO_LOG("CloudSyncOnGenerationComplete complete");
68 }
69 
CreateLcdAndThumbnail(std::shared_ptr<ThumbnailTaskData> & data)70 void IThumbnailHelper::CreateLcdAndThumbnail(std::shared_ptr<ThumbnailTaskData> &data)
71 {
72     if (data == nullptr) {
73         MEDIA_ERR_LOG("CreateLcdAndThumbnail failed, data is null");
74         return;
75     }
76     WaitStatus status;
77     bool isSuccess = DoCreateLcdAndThumbnail(data->opts_, data->thumbnailData_, status);
78     if (status == WaitStatus::INSERT) {
79         if (isSuccess && !data->thumbnailData_.tracks.empty() && (data->thumbnailData_.trigger == "0")) {
80             UpdateHighlightDbState(data->opts_, data->thumbnailData_);
81         }
82         if (data->thumbnailData_.tracks.empty()) {
83             UpdateThumbnailState(data->opts_, data->thumbnailData_, isSuccess);
84         }
85     }
86 
87     ThumbnailUtils::RecordCostTimeAndReport(data->thumbnailData_.stats);
88 }
89 
CreateLcd(std::shared_ptr<ThumbnailTaskData> & data)90 void IThumbnailHelper::CreateLcd(std::shared_ptr<ThumbnailTaskData> &data)
91 {
92     if (data == nullptr) {
93         MEDIA_ERR_LOG("CreateLcd failed, data is null");
94         return;
95     }
96     WaitStatus status;
97     DoCreateLcd(data->opts_, data->thumbnailData_, status);
98 }
99 
CreateThumbnail(std::shared_ptr<ThumbnailTaskData> & data)100 void IThumbnailHelper::CreateThumbnail(std::shared_ptr<ThumbnailTaskData> &data)
101 {
102     if (data == nullptr) {
103         MEDIA_ERR_LOG("CreateThumbnail failed, data is null");
104         return;
105     }
106     WaitStatus status;
107     bool isSuccess = DoCreateThumbnail(data->opts_, data->thumbnailData_, status);
108     if (status == WaitStatus::INSERT) {
109         UpdateThumbnailState(data->opts_, data->thumbnailData_, isSuccess);
110     }
111 
112     ThumbnailUtils::RecordCostTimeAndReport(data->thumbnailData_.stats);
113 }
114 
CreateAstc(std::shared_ptr<ThumbnailTaskData> & data)115 void IThumbnailHelper::CreateAstc(std::shared_ptr<ThumbnailTaskData> &data)
116 {
117     if (data == nullptr) {
118         MEDIA_ERR_LOG("CreateAstc failed, data is null");
119         return;
120     }
121     int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
122     bool isSuccess = DoCreateAstc(data->opts_, data->thumbnailData_);
123     UpdateThumbnailState(data->opts_, data->thumbnailData_, isSuccess);
124     MediaLibraryAstcStat::GetInstance().AddAstcInfo(startTime,
125         data->thumbnailData_.stats.scene, AstcGenScene::NOCHARGING_SCREENOFF, data->thumbnailData_.id);
126     ThumbnailUtils::RecordCostTimeAndReport(data->thumbnailData_.stats);
127 }
128 
CreateAstcEx(std::shared_ptr<ThumbnailTaskData> & data)129 void IThumbnailHelper::CreateAstcEx(std::shared_ptr<ThumbnailTaskData> &data)
130 {
131     if (data == nullptr) {
132         MEDIA_ERR_LOG("CreateAstcEx failed, data is null");
133         return;
134     }
135     WaitStatus status;
136     bool isSuccess = DoCreateAstcEx(data->opts_, data->thumbnailData_, status);
137     if (status == WaitStatus::INSERT || status == WaitStatus::WAIT_CONTINUE) {
138         UpdateThumbnailState(data->opts_, data->thumbnailData_, isSuccess);
139     }
140     ThumbnailUtils::RecordCostTimeAndReport(data->thumbnailData_.stats);
141 }
142 
DeleteMonthAndYearAstc(std::shared_ptr<ThumbnailTaskData> & data)143 void IThumbnailHelper::DeleteMonthAndYearAstc(std::shared_ptr<ThumbnailTaskData> &data)
144 {
145     if (data == nullptr) {
146         MEDIA_ERR_LOG("DeleteMonthAndYearAstc failed, data is null");
147         return;
148     }
149     if (!ThumbnailUtils::DoDeleteMonthAndYearAstc(data->opts_)) {
150         MEDIA_ERR_LOG("DeleteMonthAndYearAstc failed, key is %{public}s and %{public}s",
151             data->opts_.row.c_str(), data->opts_.dateTaken.c_str());
152     }
153 }
154 
UpdateAstcDateTaken(std::shared_ptr<ThumbnailTaskData> & data)155 void IThumbnailHelper::UpdateAstcDateTaken(std::shared_ptr<ThumbnailTaskData> &data)
156 {
157     if (data == nullptr) {
158         MEDIA_ERR_LOG("UpdateAstcDateTaken failed, data is null");
159         return;
160     }
161     if (!ThumbnailUtils::DoUpdateAstcDateTaken(data->opts_, data->thumbnailData_)) {
162         MEDIA_ERR_LOG("UpdateAstcDateTaken failed, key is %{public}s and %{public}s",
163             data->opts_.row.c_str(), data->thumbnailData_.dateTaken.c_str());
164     }
165 }
166 
AddThumbnailGenerateTask(ThumbnailGenerateExecute executor,const ThumbnailTaskType & taskType,const ThumbnailTaskPriority & priority)167 void IThumbnailHelper::AddThumbnailGenerateTask(ThumbnailGenerateExecute executor, const ThumbnailTaskType &taskType,
168     const ThumbnailTaskPriority &priority)
169 {
170     std::shared_ptr<ThumbnailGenerateWorker> thumbnailWorker =
171         ThumbnailGenerateWorkerManager::GetInstance().GetThumbnailWorker(taskType);
172     if (thumbnailWorker == nullptr) {
173         MEDIA_ERR_LOG("thumbnailWorker is null");
174         return;
175     }
176 
177     std::shared_ptr<ThumbnailTaskData> taskData = std::make_shared<ThumbnailTaskData>();
178     std::shared_ptr<ThumbnailGenerateTask> task = std::make_shared<ThumbnailGenerateTask>(executor, taskData);
179     thumbnailWorker->AddTask(task, priority);
180 }
181 
AddThumbnailGenerateTask(ThumbnailGenerateExecute executor,ThumbRdbOpt & opts,ThumbnailData & thumbData,const ThumbnailTaskType & taskType,const ThumbnailTaskPriority & priority,std::shared_ptr<ExecuteParamBuilder> param)182 void IThumbnailHelper::AddThumbnailGenerateTask(ThumbnailGenerateExecute executor, ThumbRdbOpt &opts,
183     ThumbnailData &thumbData, const ThumbnailTaskType &taskType, const ThumbnailTaskPriority &priority,
184     std::shared_ptr<ExecuteParamBuilder> param)
185 {
186     std::shared_ptr<ThumbnailGenerateWorker> thumbnailWorker =
187         ThumbnailGenerateWorkerManager::GetInstance().GetThumbnailWorker(taskType);
188     if (thumbnailWorker == nullptr) {
189         MEDIA_ERR_LOG("thumbnailWorker is null");
190         return;
191     }
192 
193     std::shared_ptr<ThumbnailTaskData> taskData = std::make_shared<ThumbnailTaskData>(opts, thumbData);
194     std::shared_ptr<ThumbnailGenerateTask> task = std::make_shared<ThumbnailGenerateTask>(executor, taskData, param);
195     thumbnailWorker->AddTask(task, priority);
196 }
197 
AddThumbnailGenBatchTask(ThumbnailGenerateExecute executor,ThumbRdbOpt & opts,ThumbnailData & thumbData,int32_t requestId)198 void IThumbnailHelper::AddThumbnailGenBatchTask(ThumbnailGenerateExecute executor,
199     ThumbRdbOpt &opts, ThumbnailData &thumbData, int32_t requestId)
200 {
201     std::shared_ptr<ThumbnailGenerateWorker> thumbnailWorker =
202         ThumbnailGenerateWorkerManager::GetInstance().GetThumbnailWorker(ThumbnailTaskType::FOREGROUND);
203     if (thumbnailWorker == nullptr) {
204         MEDIA_ERR_LOG("thumbnailWorker is null");
205         return;
206     }
207 
208     std::shared_ptr<ThumbnailTaskData> taskData = std::make_shared<ThumbnailTaskData>(opts, thumbData, requestId);
209     std::shared_ptr<ThumbnailGenerateTask> task = std::make_shared<ThumbnailGenerateTask>(executor, taskData);
210     thumbnailWorker->AddTask(task, ThumbnailTaskPriority::LOW);
211 }
212 
ThumbnailWait(bool release)213 ThumbnailWait::ThumbnailWait(bool release) : needRelease_(release)
214 {}
215 
~ThumbnailWait()216 ThumbnailWait::~ThumbnailWait()
217 {
218     if (needRelease_) {
219         Notify();
220     }
221 }
222 
223 ThumbnailMap ThumbnailWait::thumbnailMap_;
224 std::shared_mutex ThumbnailWait::mutex_;
225 
WaitFor(const shared_ptr<ThumbnailSyncStatus> & thumbnailWait,int waitMs,unique_lock<mutex> & lck)226 static bool WaitFor(const shared_ptr<ThumbnailSyncStatus> &thumbnailWait, int waitMs, unique_lock<mutex> &lck)
227 {
228     bool ret = thumbnailWait->cond_.wait_for(lck, chrono::milliseconds(waitMs),
229         [thumbnailWait]() { return thumbnailWait->isSyncComplete_; });
230     if (!ret) {
231         MEDIA_INFO_LOG("IThumbnailHelper::Wait wait for lock timeout");
232     }
233     return ret;
234 }
235 
InsertAndWait(const string & id,ThumbnailType type,const string & dateModified)236 WaitStatus ThumbnailWait::InsertAndWait(const string &id, ThumbnailType type, const string &dateModified)
237 {
238     id_ = id + ThumbnailUtils::GetThumbnailSuffix(type);
239     dateModified_ = dateModified;
240     unique_lock<shared_mutex> writeLck(mutex_);
241     auto iter = thumbnailMap_.find(id_);
242     if (iter != thumbnailMap_.end()) {
243         auto thumbnailWait = iter->second;
244         unique_lock<mutex> lck(thumbnailWait->mtx_);
245 
246         // As data Source has changed, allowing this insertion to proceed and update dateModified
247         if (thumbnailWait->latestDateModified_ < dateModified) {
248             MEDIA_INFO_LOG("DateModified changed, continue to generate thumbnail, id: %{public}s, last: %{public}s,"
249                 "new:  %{public}s", id_.c_str(), thumbnailWait->latestDateModified_.c_str(), dateModified.c_str());
250             thumbnailWait->latestDateModified_ = dateModified;
251             return WaitStatus::WAIT_CONTINUE;
252         }
253 
254         writeLck.unlock();
255         MEDIA_INFO_LOG("Waiting for thumbnail generation, id: %{public}s", id_.c_str());
256         thumbnailWait->cond_.wait(lck, [weakPtr = weak_ptr(thumbnailWait)]() {
257             if (auto sharedPtr = weakPtr.lock()) {
258                 return sharedPtr->isSyncComplete_;
259             } else {
260                 return true;
261             }
262         });
263         if (thumbnailWait->isCreateThumbnailSuccess_) {
264             MEDIA_INFO_LOG("Thumbnail generated successfully");
265             return WaitStatus::WAIT_SUCCESS;
266         } else {
267             MEDIA_ERR_LOG("Failed to generate thumbnail");
268             return WaitStatus::WAIT_FAILED;
269         }
270     } else {
271         shared_ptr<ThumbnailSyncStatus> thumbnailWait = make_shared<ThumbnailSyncStatus>();
272         thumbnailWait->latestDateModified_ = dateModified;
273         thumbnailMap_.insert(ThumbnailMap::value_type(id_, thumbnailWait));
274         return WaitStatus::INSERT;
275     }
276 }
277 
CheckCloudReadResult(CloudLoadType cloudLoadType,CloudReadStatus status)278 WaitStatus CheckCloudReadResult(CloudLoadType cloudLoadType, CloudReadStatus status)
279 {
280     switch (status) {
281         case CloudReadStatus::FAIL:
282             MEDIA_INFO_LOG("Fail to cloud read thumbnail, type: %{public}d", cloudLoadType);
283             return WaitStatus::WAIT_FAILED;
284             break;
285         case CloudReadStatus::SUCCESS:
286             MEDIA_INFO_LOG("Success to cloud read thumbnail, type: %{public}d", cloudLoadType);
287             return WaitStatus::WAIT_SUCCESS;
288             break;
289         case CloudReadStatus::START:
290             MEDIA_INFO_LOG("Continue to cloud read thumbnail, type: %{public}d", cloudLoadType);
291             return WaitStatus::WAIT_CONTINUE;
292             break;
293         default:
294             break;
295     }
296     return WaitStatus::WAIT_FAILED;
297 }
298 
CloudInsertAndWait(const string & id,CloudLoadType cloudLoadType)299 WaitStatus ThumbnailWait::CloudInsertAndWait(const string &id, CloudLoadType cloudLoadType)
300 {
301     id_ = id + ".cloud";
302     unique_lock<shared_mutex> writeLck(mutex_);
303     auto iter = thumbnailMap_.find(id_);
304     if (iter != thumbnailMap_.end()) {
305         auto thumbnailWait = iter->second;
306         unique_lock<mutex> lck(thumbnailWait->mtx_);
307         writeLck.unlock();
308         MEDIA_INFO_LOG("Waiting for thumbnail generation, id: %{public}s", id_.c_str());
309         thumbnailWait->cond_.wait(lck, [weakPtr = weak_ptr(thumbnailWait)]() {
310             if (auto sharedPtr = weakPtr.lock()) {
311                 return sharedPtr->isSyncComplete_;
312             } else {
313                 return true;
314             }
315         });
316         thumbnailWait->isSyncComplete_ = false;
317         thumbnailWait->cloudLoadType_ = cloudLoadType;
318         unique_lock<shared_mutex> evokeLck(mutex_);
319         thumbnailMap_.emplace(ThumbnailMap::value_type(id_, thumbnailWait));
320         evokeLck.unlock();
321 
322         if (cloudLoadType == CLOUD_DOWNLOAD) {
323             MEDIA_INFO_LOG("Continue to generate thumbnail");
324             return WaitStatus::WAIT_CONTINUE;
325         }
326         if (cloudLoadType == CLOUD_READ_THUMB) {
327             return CheckCloudReadResult(cloudLoadType, thumbnailWait->CloudLoadThumbnailStatus_);
328         }
329         if (cloudLoadType == CLOUD_READ_LCD) {
330             return CheckCloudReadResult(cloudLoadType, thumbnailWait->CloudLoadLcdStatus_);
331         }
332         MEDIA_INFO_LOG("Cloud generate thumbnail successfully");
333         return WaitStatus::WAIT_SUCCESS;
334     } else {
335         shared_ptr<ThumbnailSyncStatus> thumbnailWait = make_shared<ThumbnailSyncStatus>();
336         thumbnailWait->cloudLoadType_ = cloudLoadType;
337         thumbnailMap_.insert(ThumbnailMap::value_type(id_, thumbnailWait));
338         return WaitStatus::INSERT;
339     }
340 }
341 
TrySaveCurrentPixelMap(ThumbnailData & data,ThumbnailType type)342 bool ThumbnailWait::TrySaveCurrentPixelMap(ThumbnailData &data, ThumbnailType type)
343 {
344     ThumbnailType idType = (type == ThumbnailType::LCD || type == ThumbnailType::LCD_EX) ?
345         ThumbnailType::LCD : ThumbnailType::THUMB;
346     id_ = data.id + ThumbnailUtils::GetThumbnailSuffix(idType);
347     MEDIA_INFO_LOG("Save current pixelMap, path: %{public}s, type: %{public}d",
348         DfxUtils::GetSafePath(data.path).c_str(), type);
349     unique_lock<shared_mutex> writeLck(mutex_);
350     auto iter = thumbnailMap_.find(id_);
351     if (iter != thumbnailMap_.end()) {
352         auto thumbnailWait = iter->second;
353         unique_lock<mutex> lck(thumbnailWait->mtx_);
354         writeLck.unlock();
355         if (!thumbnailWait->CheckSavedFileMap(data.id, type, data.dateModified)) {
356             MEDIA_ERR_LOG("TrySaveCurrentPixelMap cancelled, latest file exists, path: %{public}s",
357                 DfxUtils::GetSafePath(data.path).c_str());
358             return false;
359         }
360 
361         int err = ThumbnailUtils::TrySaveFile(data, type);
362         if (err < 0) {
363             MEDIA_ERR_LOG("TrySaveCurrentPixelMap failed: %{public}d, path: %{public}s", err,
364                 DfxUtils::GetSafePath(data.path).c_str());
365             return false;
366         }
367 
368         if (!thumbnailWait->UpdateSavedFileMap(data.id, type, data.dateModified)) {
369             MEDIA_ERR_LOG("UpdateSavedFileMap failed while save pixelMap, path: %{public}s",
370                 DfxUtils::GetSafePath(data.path).c_str());
371             return false;
372         }
373     } else {
374         MEDIA_ERR_LOG("TrySaveCurrentPixelMap cancelled, corresponding task has finished, path: %{public}s",
375             DfxUtils::GetSafePath(data.path).c_str());
376         return false;
377     }
378     return true;
379 }
380 
TrySaveCurrentPicture(ThumbnailData & data,bool isSourceEx,const string & tempOutputPath)381 bool ThumbnailWait::TrySaveCurrentPicture(ThumbnailData &data, bool isSourceEx, const string &tempOutputPath)
382 {
383     id_ = data.id + ThumbnailUtils::GetThumbnailSuffix(ThumbnailType::LCD);
384     MEDIA_INFO_LOG("Save current picture, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
385     unique_lock<shared_mutex> writeLck(mutex_);
386     auto iter = thumbnailMap_.find(id_);
387     if (iter != thumbnailMap_.end()) {
388         auto thumbnailWait = iter->second;
389         unique_lock<mutex> lck(thumbnailWait->mtx_);
390         writeLck.unlock();
391         ThumbnailType lcdType = isSourceEx ? ThumbnailType::LCD_EX : ThumbnailType::LCD;
392         if (!thumbnailWait->CheckSavedFileMap(data.id, lcdType, data.dateModified)) {
393             MEDIA_ERR_LOG("TrySaveCurrentPicture cancelled, latest file exists, path: %{public}s",
394                 DfxUtils::GetSafePath(data.path).c_str());
395             ThumbnailUtils::CancelAfterPacking(tempOutputPath);
396             return false;
397         }
398 
399         if (!ThumbnailUtils::SaveAfterPacking(data, isSourceEx, tempOutputPath)) {
400             MEDIA_ERR_LOG("TrySaveCurrentPicture failed, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
401             return false;
402         }
403 
404         if (!thumbnailWait->UpdateSavedFileMap(data.id, lcdType, data.dateModified)) {
405             MEDIA_ERR_LOG("UpdateSavedFileMap failed while save picture, path: %{public}s",
406                 DfxUtils::GetSafePath(data.path).c_str());
407             return false;
408         }
409     } else {
410         MEDIA_ERR_LOG("TrySaveCurrentPicture cancelled, corresponding task has finished, path: %{public}s",
411             DfxUtils::GetSafePath(data.path).c_str());
412         ThumbnailUtils::CancelAfterPacking(tempOutputPath);
413         return false;
414     }
415     return true;
416 }
417 
CheckAndWait(const string & id,bool isLcd)418 void ThumbnailWait::CheckAndWait(const string &id, bool isLcd)
419 {
420     id_ = id;
421 
422     if (isLcd) {
423         id_ += THUMBNAIL_LCD_SUFFIX;
424     } else {
425         id_ += THUMBNAIL_THUMB_SUFFIX;
426     }
427     shared_lock<shared_mutex> readLck(mutex_);
428     auto iter = thumbnailMap_.find(id_);
429     if (iter != thumbnailMap_.end()) {
430         auto thumbnailWait = iter->second;
431         unique_lock<mutex> lck(thumbnailWait->mtx_);
432         readLck.unlock();
433         WaitFor(thumbnailWait, WAIT_FOR_MS, lck);
434     }
435 }
436 
UpdateThumbnailMap()437 void ThumbnailWait::UpdateThumbnailMap()
438 {
439     unique_lock<shared_mutex> writeLck(mutex_);
440     auto iter = thumbnailMap_.find(id_);
441     if (iter != thumbnailMap_.end()) {
442         auto thumbnailWait = iter->second;
443         {
444             unique_lock<mutex> lck(thumbnailWait->mtx_);
445             writeLck.unlock();
446             thumbnailWait->isCreateThumbnailSuccess_ = true;
447             needRelease_ = thumbnailWait->latestDateModified_ == dateModified_;
448         }
449         if (!needRelease_) {
450             MEDIA_INFO_LOG("Latest task has come, id: %{public}s", id_.c_str());
451         }
452     } else {
453         MEDIA_ERR_LOG("Update ThumbnailMap failed, id: %{public}s", id_.c_str());
454     }
455 }
456 
UpdateCloudLoadThumbnailMap(CloudLoadType cloudLoadType,bool isLoadSuccess)457 void ThumbnailWait::UpdateCloudLoadThumbnailMap(CloudLoadType cloudLoadType, bool isLoadSuccess)
458 {
459     unique_lock<shared_mutex> writeLck(mutex_);
460     auto iter = thumbnailMap_.find(id_);
461     if (iter != thumbnailMap_.end()) {
462         auto thumbnailWait = iter->second;
463         {
464             unique_lock<mutex> lck(thumbnailWait->mtx_);
465             writeLck.unlock();
466             switch (cloudLoadType) {
467                 case CLOUD_READ_THUMB:
468                     thumbnailWait->CloudLoadThumbnailStatus_ =
469                         isLoadSuccess ? CloudReadStatus::SUCCESS : CloudReadStatus::FAIL;
470                     break;
471                 case CLOUD_READ_LCD:
472                     thumbnailWait->CloudLoadLcdStatus_ =
473                         isLoadSuccess ? CloudReadStatus::SUCCESS : CloudReadStatus::FAIL;
474                     break;
475                 case CLOUD_DOWNLOAD:
476                     thumbnailWait->CloudLoadThumbnailStatus_ =
477                         isLoadSuccess ? CloudReadStatus::SUCCESS : CloudReadStatus::FAIL;
478                     thumbnailWait->CloudLoadLcdStatus_ =
479                         isLoadSuccess ? CloudReadStatus::SUCCESS : CloudReadStatus::FAIL;
480                     break;
481                 default:
482                     break;
483             }
484         }
485     } else {
486         MEDIA_ERR_LOG("Update CloudLoadThumbnailMap failed, id: %{public}s", id_.c_str());
487     }
488 }
489 
Notify()490 void ThumbnailWait::Notify()
491 {
492     unique_lock<shared_mutex> writeLck(mutex_);
493     auto iter = thumbnailMap_.find(id_);
494     if (iter != thumbnailMap_.end()) {
495         auto thumbnailWait = iter->second;
496         {
497             unique_lock<mutex> lck(thumbnailWait->mtx_);
498             if (!dateModified_.empty() && thumbnailWait->latestDateModified_ > dateModified_) {
499                 MEDIA_INFO_LOG("Latest task has come, no need to notify, id: %{public}s", id_.c_str());
500                 return;
501             }
502             thumbnailMap_.erase(iter);
503             writeLck.unlock();
504             thumbnailWait->isSyncComplete_ = true;
505         }
506         if (thumbnailWait->cloudLoadType_ == CloudLoadType::NONE) {
507             thumbnailWait->cond_.notify_all();
508         } else {
509             thumbnailWait->cond_.notify_one();
510         }
511     }
512 }
513 
CheckSavedFileMap(const string & id,ThumbnailType type,const string & dateModified)514 bool ThumbnailSyncStatus::CheckSavedFileMap(const string &id, ThumbnailType type, const string &dateModified)
515 {
516     std::string saveId = id + ThumbnailUtils::GetThumbnailSuffix(type);
517     auto iter = latestSavedFileMap_.find(id);
518     if (iter != latestSavedFileMap_.end() && (iter->second > dateModified)) {
519         return false;
520     }
521     return true;
522 }
523 
UpdateSavedFileMap(const string & id,ThumbnailType type,const string & dateModified)524 bool ThumbnailSyncStatus::UpdateSavedFileMap(const string &id, ThumbnailType type, const string &dateModified)
525 {
526     std::string saveId = id + ThumbnailUtils::GetThumbnailSuffix(type);
527     auto iter = latestSavedFileMap_.find(id);
528     if (iter != latestSavedFileMap_.end()) {
529         if (iter->second > dateModified) {
530             return false;
531         } else {
532             iter->second = dateModified;
533         }
534     } else {
535         latestSavedFileMap_.emplace(id, dateModified);
536     }
537     return true;
538 }
539 
TryLoadSource(ThumbRdbOpt & opts,ThumbnailData & data)540 bool IThumbnailHelper::TryLoadSource(ThumbRdbOpt &opts, ThumbnailData &data)
541 {
542     if (!data.source.IsEmptySource()) {
543         return true;
544     }
545 
546     if (data.loaderOpts.loadingStates.empty()) {
547         MEDIA_ERR_LOG("try load source failed, the loading source states is empty.");
548         return false;
549     }
550 
551     if (!ThumbnailUtils::LoadSourceImage(data)) {
552         if (opts.path.empty()) {
553             MEDIA_ERR_LOG("LoadSourceImage faild, %{public}s", DfxUtils::GetSafePath(data.path).c_str());
554             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
555                 {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
556             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
557             return false;
558         } else {
559             opts.path = "";
560             ThumbnailUtils::GetThumbnailInfo(opts, data);
561             if (access(data.path.c_str(), F_OK) == 0) {
562                 return true;
563             }
564             if (!ThumbnailUtils::LoadSourceImage(data)) {
565                 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
566                     {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN}, {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
567                 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
568                 return false;
569             }
570         }
571     }
572     return true;
573 }
574 
TrySavePixelMap(ThumbnailData & data,ThumbnailType type)575 bool IThumbnailHelper::TrySavePixelMap(ThumbnailData &data, ThumbnailType type)
576 {
577     if (!data.needCheckWaitStatus) {
578         int err = ThumbnailUtils::TrySaveFile(data, type);
579         if (err < 0) {
580             MEDIA_ERR_LOG("No wait TrySavePixelMap failed: %{public}d, path: %{public}s", err,
581                 DfxUtils::GetSafePath(data.path).c_str());
582             return false;
583         }
584         return true;
585     }
586     ThumbnailWait thumbnailWait(false);
587     if (!thumbnailWait.TrySaveCurrentPixelMap(data, type)) {
588         MEDIA_ERR_LOG("TrySavePixelMap failed, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
589         return false;
590     }
591     return true;
592 }
593 
TrySavePicture(ThumbnailData & data,bool isSourceEx,const string & tempOutputPath)594 bool IThumbnailHelper::TrySavePicture(ThumbnailData &data, bool isSourceEx, const string &tempOutputPath)
595 {
596     if (!data.needCheckWaitStatus) {
597         if (!ThumbnailUtils::SaveAfterPacking(data, isSourceEx, tempOutputPath)) {
598             MEDIA_ERR_LOG("No wait TrySavePicture failed, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
599             return false;
600         }
601         return true;
602     }
603     ThumbnailWait thumbnailWait(false);
604     if (!thumbnailWait.TrySaveCurrentPicture(data, isSourceEx, tempOutputPath)) {
605         MEDIA_ERR_LOG("TrySavePicture failed, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
606         return false;
607     }
608     return true;
609 }
610 
DoCreateLcd(ThumbRdbOpt & opts,ThumbnailData & data,WaitStatus & ret)611 bool IThumbnailHelper::DoCreateLcd(ThumbRdbOpt &opts, ThumbnailData &data, WaitStatus &ret)
612 {
613     MEDIA_INFO_LOG("Start DoCreateLcd, id: %{public}s, path: %{public}s",
614         data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
615     ThumbnailWait thumbnailWait(true);
616     ret = thumbnailWait.InsertAndWait(data.id, ThumbnailType::LCD, data.dateModified);
617     data.needCheckWaitStatus = true;
618     if (ret != WaitStatus::INSERT && ret != WaitStatus::WAIT_CONTINUE) {
619         return ret == WaitStatus::WAIT_SUCCESS;
620     }
621 
622     if (!IsCreateLcdSuccess(opts, data)) {
623         MEDIA_ERR_LOG("Fail to create lcd, path: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
624         return false;
625     }
626 
627     if (data.orientation != 0 && !IsCreateLcdExSuccess(opts, data)) {
628         MEDIA_ERR_LOG("Fail to create lcdEx, path: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
629     }
630     thumbnailWait.UpdateThumbnailMap();
631     data.needCheckWaitStatus = false;
632     return true;
633 }
634 
UpdateLcdDbState(ThumbRdbOpt & opts,ThumbnailData & data)635 void UpdateLcdDbState(ThumbRdbOpt &opts, ThumbnailData &data)
636 {
637     if (opts.table != PhotoColumn::PHOTOS_TABLE) {
638         return;
639     }
640     if (data.isNeedStoreSize) {
641         StoreThumbnailSize(opts, data);
642     }
643     data.isNeedStoreSize = true;
644     int err = 0;
645     if (!ThumbnailUtils::UpdateLcdInfo(opts, data, err)) {
646         MEDIA_INFO_LOG("UpdateLcdInfo faild err : %{public}d", err);
647     }
648 }
649 
UpdateHighlightDbState(ThumbRdbOpt & opts,ThumbnailData & data)650 void IThumbnailHelper::UpdateHighlightDbState(ThumbRdbOpt &opts, ThumbnailData &data)
651 {
652     if (opts.table != PhotoColumn::HIGHLIGHT_TABLE) {
653         return;
654     }
655     int err = 0;
656     if (!ThumbnailUtils::UpdateHighlightInfo(opts, data, err)) {
657         MEDIA_ERR_LOG("UpdateHighlightInfo faild err : %{public}d", err);
658     }
659 }
660 
SaveLcdPictureSource(ThumbRdbOpt & opts,ThumbnailData & data,bool isSourceEx)661 bool IThumbnailHelper::SaveLcdPictureSource(ThumbRdbOpt &opts, ThumbnailData &data, bool isSourceEx)
662 {
663     shared_ptr<Picture> lcdSource = isSourceEx ? data.source.GetPictureEx() : data.source.GetPicture();
664     if (lcdSource == nullptr) {
665         MEDIA_ERR_LOG("SaveLcdPictureSource failed, lcdSource is null");
666         return false;
667     }
668     if (lcdSource->GetMainPixel() == nullptr || lcdSource->GetGainmapPixelMap() == nullptr) {
669         MEDIA_ERR_LOG("SaveLcdPictureSource failed, mainpixel exist: %{public}d, gainMap exist: %{public}d",
670             lcdSource->GetMainPixel() == nullptr, lcdSource->GetGainmapPixelMap() == nullptr);
671         return false;
672     }
673     bool shouldReverseSize = !isSourceEx && (data.orientation % FLAT_ANGLE != 0);
674     int lcdDesiredWidth = shouldReverseSize ? data.lcdDesiredSize.height : data.lcdDesiredSize.width;
675     int lcdDesiredHeight = shouldReverseSize ? data.lcdDesiredSize.width : data.lcdDesiredSize.height;
676     std::shared_ptr<Picture> copySource;
677     if (lcdDesiredWidth != lcdSource->GetMainPixel()->GetWidth()) {
678         MEDIA_INFO_LOG("Copy and resize picture source for lcd desiredSize: %{public}s",
679             DfxUtils::GetSafePath(data.path).c_str());
680         copySource = ThumbnailImageFrameWorkUtils::CopyPictureSource(lcdSource);
681         CHECK_AND_RETURN_RET_LOG(copySource != nullptr, false, "SaveLcdPictureSource failed, CopyPictureSource failed");
682         if (lcdSource->GetMainPixel()->GetWidth() * lcdSource->GetMainPixel()->GetHeight() == 0) {
683             MEDIA_ERR_LOG("SaveLcdPictureSource failed, invalid mainpixel size");
684             return false;
685         }
686         float widthScale = (1.0f * lcdDesiredWidth) / lcdSource->GetMainPixel()->GetWidth();
687         float heightScale = (1.0f * lcdDesiredHeight) / lcdSource->GetMainPixel()->GetHeight();
688         lcdSource->GetMainPixel()->scale(widthScale, heightScale);
689         lcdSource->GetGainmapPixelMap()->scale(widthScale, heightScale);
690     }
691     std::string tempOutputPath;
692     if (!ThumbnailUtils::CompressPicture(data, isSourceEx, tempOutputPath)) {
693         MEDIA_ERR_LOG("SaveLcdPictureSource failed, CompressPicture failed");
694         return false;
695     }
696     if (!TrySavePicture(data, isSourceEx, tempOutputPath)) {
697         MEDIA_ERR_LOG("SaveLcdPictureSource failed, save picture failed");
698         return false;
699     }
700     if (copySource != nullptr) {
701         lcdSource = copySource;
702     }
703     if (!isSourceEx) {
704         UpdateLcdDbState(opts, data);
705     }
706     return true;
707 }
708 
SaveLcdPixelMapSource(ThumbRdbOpt & opts,ThumbnailData & data,bool isSourceEx)709 bool IThumbnailHelper::SaveLcdPixelMapSource(ThumbRdbOpt &opts, ThumbnailData &data, bool isSourceEx)
710 {
711     shared_ptr<PixelMap> lcdSource = isSourceEx ? data.source.GetPixelMapEx() : data.source.GetPixelMap();
712     if (lcdSource == nullptr) {
713         MEDIA_ERR_LOG("SaveLcdPixelMapSource failed, lcdSource is null");
714         return false;
715     }
716     int lcdDesiredWidth;
717     int lcdDesiredHeight;
718     if (isSourceEx) {
719         lcdDesiredWidth = data.lcdDesiredSize.width;
720         lcdDesiredHeight = data.lcdDesiredSize.height;
721     } else {
722         lcdDesiredWidth = data.orientation % FLAT_ANGLE == 0 ? data.lcdDesiredSize.width : data.lcdDesiredSize.height;
723         lcdDesiredHeight = data.orientation % FLAT_ANGLE == 0 ? data.lcdDesiredSize.height : data.lcdDesiredSize.width;
724     }
725     if (lcdDesiredWidth != lcdSource->GetWidth()) {
726         MEDIA_INFO_LOG("Copy and resize data source for lcd desiredSize: %{public}s",
727             DfxUtils::GetSafePath(data.path).c_str());
728         auto copySource = ThumbnailImageFrameWorkUtils::CopyPixelMapSource(lcdSource);
729         lcdSource = std::move(copySource);
730         CHECK_AND_RETURN_RET_LOG(lcdSource != nullptr, false, "LcdSource is nullptr");
731         if (lcdSource->GetWidth() * lcdSource->GetHeight() == 0) {
732             MEDIA_ERR_LOG("CompressImage failed, invalid lcdSource");
733             return false;
734         }
735         float widthScale = (1.0f * lcdDesiredWidth) / lcdSource->GetWidth();
736         float heightScale = (1.0f * lcdDesiredHeight) / lcdSource->GetHeight();
737         lcdSource->scale(widthScale, heightScale);
738     }
739     if (!ThumbnailUtils::CompressImage(lcdSource, data.lcd, false, false, data.thumbnailQuality)) {
740         MEDIA_ERR_LOG("CompressImage failed");
741         return false;
742     }
743 
744     if (!TrySavePixelMap(data, isSourceEx ? ThumbnailType::LCD_EX : ThumbnailType::LCD)) {
745         MEDIA_ERR_LOG("SaveLcd PixelMap failed: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
746         return false;
747     }
748 
749     data.lcd.clear();
750     if (!isSourceEx) {
751         UpdateLcdDbState(opts, data);
752     }
753     return true;
754 }
755 
IsCreateLcdSuccess(ThumbRdbOpt & opts,ThumbnailData & data)756 bool IThumbnailHelper::IsCreateLcdSuccess(ThumbRdbOpt &opts, ThumbnailData &data)
757 {
758     data.loaderOpts.decodeInThumbSize = false;
759     data.loaderOpts.isHdr = true;
760     if (!TryLoadSource(opts, data)) {
761         MEDIA_ERR_LOG("load source is nullptr path: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
762         return false;
763     }
764 
765     if (data.source.IsEmptySource()) {
766         MEDIA_ERR_LOG("Fail to create lcd, source is nullptr");
767         return false;
768     }
769 
770     if (data.source.HasPictureSource()) {
771         return SaveLcdPictureSource(opts, data, false);
772     } else {
773         return SaveLcdPixelMapSource(opts, data, false);
774     }
775 }
776 
IsCreateLcdExSuccess(ThumbRdbOpt & opts,ThumbnailData & data)777 bool IThumbnailHelper::IsCreateLcdExSuccess(ThumbRdbOpt &opts, ThumbnailData &data)
778 {
779     if (!data.isLocalFile) {
780         MEDIA_INFO_LOG("Create lcd when cloud loading, no need to create THM_EX, path: %{public}s, id: %{public}s",
781             DfxUtils::GetSafePath(opts.path).c_str(), data.id.c_str());
782         return false;
783     }
784 
785     string fileName = GetThumbnailPath(data.path, THUMBNAIL_LCD_EX_SUFFIX);
786     string dirName = MediaFileUtils::GetParentPath(fileName);
787     if (!MediaFileUtils::CreateDirectory(dirName)) {
788         MEDIA_ERR_LOG("Fail to create directory, fileName: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
789         return false;
790     }
791 
792     if (data.source.IsEmptySource()) {
793         MEDIA_ERR_LOG("Fail to create lcdEx, source is nullptr");
794         return false;
795     }
796 
797     if (data.source.HasPictureSource()) {
798         return SaveLcdPictureSource(opts, data, true);
799     } else {
800         return SaveLcdPixelMapSource(opts, data, true);
801     }
802 }
803 
GenThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,const ThumbnailType type)804 bool IThumbnailHelper::GenThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, const ThumbnailType type)
805 {
806     auto pixelMap = data.source.GetPixelMap();
807     if (pixelMap == nullptr) {
808         MEDIA_ERR_LOG("source is nullptr when generate type: %{public}s", TYPE_NAME_MAP.at(type).c_str());
809         return false;
810     }
811 
812     if (type == ThumbnailType::THUMB || type == ThumbnailType::THUMB_ASTC) {
813         if (!ThumbnailUtils::CompressImage(pixelMap, type == ThumbnailType::THUMB ? data.thumbnail : data.thumbAstc,
814             type == ThumbnailType::THUMB_ASTC)) {
815             MEDIA_ERR_LOG("CompressImage faild id %{public}s", opts.row.c_str());
816             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
817                 {KEY_OPT_FILE, opts.path}, {KEY_OPT_TYPE, OptType::THUMB}};
818             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
819             return false;
820         }
821     } else if (type == ThumbnailType::MTH_ASTC || type == ThumbnailType::YEAR_ASTC) {
822         if (!ThumbnailUtils::CheckDateTaken(opts, data)) {
823             MEDIA_ERR_LOG("CheckDateTaken failed in GenThumbnail");
824             return false;
825         }
826         if (!GenMonthAndYearAstcData(data, type)) {
827             MEDIA_ERR_LOG("GenMonthAndYearAstcData failed in GenThumbnail");
828             return false;
829         }
830     } else {
831         MEDIA_ERR_LOG("invalid thumbnail type: %{public}d", type);
832         return false;
833     }
834 
835     if (!TrySavePixelMap(data, type)) {
836         MEDIA_ERR_LOG("SaveThumbnailData failed: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
837         return false;
838     }
839     data.thumbnail.clear();
840     return true;
841 }
842 
GenThumbnailEx(ThumbRdbOpt & opts,ThumbnailData & data)843 bool IThumbnailHelper::GenThumbnailEx(ThumbRdbOpt &opts, ThumbnailData &data)
844 {
845     if (!data.isLocalFile) {
846         MEDIA_INFO_LOG("Create thumb when cloud loading, no need to create THM_EX, path: %{public}s, id: %{public}s",
847             DfxUtils::GetSafePath(opts.path).c_str(), data.id.c_str());
848         return false;
849     }
850 
851     string fileName = GetThumbnailPath(data.path, THUMBNAIL_THUMB_EX_SUFFIX);
852     string dirName = MediaFileUtils::GetParentPath(fileName);
853     if (!MediaFileUtils::CreateDirectory(dirName)) {
854         MEDIA_ERR_LOG("Fail to create directory, fileName: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
855         return false;
856     }
857 
858     auto pixelMapEx = data.source.GetPixelMapEx();
859     if (pixelMapEx == nullptr) {
860         MEDIA_ERR_LOG("sourceEx is nullptr when generate thumbnailEx, path: %{public}s",
861             DfxUtils::GetSafePath(opts.path).c_str());
862         return false;
863     }
864 
865     if (!ThumbnailUtils::CompressImage(pixelMapEx, data.thumbnail, false)) {
866         MEDIA_ERR_LOG("CompressImage failed id %{public}s", opts.row.c_str());
867         return false;
868     }
869 
870     if (!TrySavePixelMap(data, ThumbnailType::THUMB_EX)) {
871         MEDIA_ERR_LOG("SaveThumbnailEx failed: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
872         return false;
873     }
874     data.thumbnail.clear();
875     return true;
876 }
877 
GenMonthAndYearAstcData(ThumbnailData & data,const ThumbnailType type)878 bool IThumbnailHelper::GenMonthAndYearAstcData(ThumbnailData &data, const ThumbnailType type)
879 {
880     Size size;
881     if (type == ThumbnailType::MTH_ASTC) {
882         size = {DEFAULT_MTH_SIZE, DEFAULT_MTH_SIZE };
883     } else if (type == ThumbnailType::YEAR_ASTC) {
884         size = {DEFAULT_YEAR_SIZE, DEFAULT_YEAR_SIZE };
885     } else {
886         MEDIA_ERR_LOG("invalid thumbnail type");
887         return false;
888     }
889     ThumbnailUtils::GenTargetPixelmap(data, size);
890     auto pixelMap = data.source.GetPixelMap();
891 #ifdef IMAGE_COLORSPACE_FLAG
892     if (pixelMap->ApplyColorSpace(ColorManager::ColorSpaceName::DISPLAY_P3) != E_OK) {
893         MEDIA_ERR_LOG("ApplyColorSpace to p3 failed");
894     }
895 #endif
896     if (!ThumbnailUtils::CompressImage(pixelMap,
897         (type == ThumbnailType::MTH_ASTC) ? data.monthAstc : data.yearAstc, true)) {
898         MEDIA_ERR_LOG("CompressImage to astc failed");
899         return false;
900     }
901     return true;
902 }
903 
904 // After all thumbnails are generated, the value of column "thumbnail_ready" in rdb needs to be updated,
905 // And if generate successfully, application should receive a notification at the same time.
UpdateThumbnailState(const ThumbRdbOpt & opts,ThumbnailData & data,const bool isSuccess)906 bool IThumbnailHelper::UpdateThumbnailState(const ThumbRdbOpt &opts, ThumbnailData &data, const bool isSuccess)
907 {
908     if (data.fileUri.empty()) {
909         data.fileUri = MediaFileUtils::GetUriByExtrConditions(PhotoColumn::DEFAULT_PHOTO_URI + "/", data.id,
910             MediaFileUtils::GetExtraUri(data.displayName, data.path));
911     }
912     return isSuccess ? UpdateSuccessState(opts, data) : UpdateFailState(opts, data);
913 }
914 
915 // This method has to be called before updating rdb
IsPhotoVisible(const ThumbRdbOpt & opts,const ThumbnailData & data)916 static int32_t IsPhotoVisible(const ThumbRdbOpt &opts, const ThumbnailData &data)
917 {
918     vector<string> columns = {
919         PhotoColumn::PHOTO_THUMBNAIL_VISIBLE
920     };
921     if (data.id.empty() && opts.row.empty()) {
922         MEDIA_ERR_LOG("SendThumbNotify thumb is empty");
923         return 0;
924     }
925     string fileId = data.id.empty() ? opts.row : data.id;
926     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + fileId;
927     RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
928     rdbPredicates.SetWhereClause(strQueryCondition);
929     if (opts.store == nullptr) {
930         MEDIA_ERR_LOG("SendThumbNotify opts.store is nullptr");
931         return 0;
932     }
933     auto resultSet = opts.store->QueryByStep(rdbPredicates, columns);
934     if (resultSet == nullptr) {
935         MEDIA_ERR_LOG("SendThumbNotify result is null");
936         return 0;
937     }
938     auto ret = resultSet->GoToFirstRow();
939     if (ret != NativeRdb::E_OK) {
940         MEDIA_ERR_LOG("SendThumbNotify go to first row failed");
941         return 0;
942     }
943     return GetInt32Val(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, resultSet);
944 }
945 
UpdateSuccessState(const ThumbRdbOpt & opts,const ThumbnailData & data)946 bool IThumbnailHelper::UpdateSuccessState(const ThumbRdbOpt &opts, const ThumbnailData &data)
947 {
948     int thumbnailVisible = IsPhotoVisible(opts, data);
949     int32_t err = UpdateThumbDbState(opts, data);
950     if (err != E_OK) {
951         MEDIA_ERR_LOG("update thumbnail_ready failed, err = %{public}d", err);
952         return false;
953     }
954 
955     auto watch = MediaLibraryNotify::GetInstance();
956     if (watch == nullptr) {
957         MEDIA_ERR_LOG("SendThumbNotify watch is nullptr");
958         return false;
959     }
960     if (thumbnailVisible) {
961         watch->Notify(data.fileUri, NotifyType::NOTIFY_THUMB_UPDATE);
962     } else {
963         watch->Notify(data.fileUri, NotifyType::NOTIFY_THUMB_ADD);
964     }
965     return true;
966 }
967 
UpdateFailState(const ThumbRdbOpt & opts,const ThumbnailData & data)968 bool IThumbnailHelper::UpdateFailState(const ThumbRdbOpt &opts, const ThumbnailData &data)
969 {
970     if (opts.store == nullptr) {
971         MEDIA_ERR_LOG("opts.store is nullptr");
972         return false;
973     }
974     ValuesBucket values;
975     int changedRows;
976     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, static_cast<int64_t>(ThumbnailReady::GENERATE_THUMB_RETRY));
977     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, 1);
978     int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
979         vector<string> { data.id });
980     if (err != NativeRdb::E_OK) {
981         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
982         return false;
983     }
984     return true;
985 }
986 
UpdateThumbDbState(const ThumbRdbOpt & opts,const ThumbnailData & data)987 int32_t IThumbnailHelper::UpdateThumbDbState(const ThumbRdbOpt &opts, const ThumbnailData &data)
988 {
989     ValuesBucket values;
990     int changedRows;
991     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, MediaFileUtils::UTCTimeMilliSeconds());
992     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, 1);
993     Size lcdSize;
994     if (ThumbnailUtils::GetLocalThumbSize(data, ThumbnailType::LCD, lcdSize)) {
995         ThumbnailUtils::SetThumbnailSizeValue(values, lcdSize, PhotoColumn::PHOTO_LCD_SIZE);
996         values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(LcdReady::GENERATE_LCD_COMPLETED));
997     }
998     Size thumbSize;
999     if (ThumbnailUtils::GetLocalThumbSize(data, ThumbnailType::THUMB, thumbSize)) {
1000         ThumbnailUtils::SetThumbnailSizeValue(values, thumbSize, PhotoColumn::PHOTO_THUMB_SIZE);
1001     }
1002     int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1003         vector<string> { data.id });
1004     StoreThumbnailSize(opts, data);
1005     if (err != NativeRdb::E_OK) {
1006         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1007         return E_ERR;
1008     }
1009     return E_OK;
1010 }
1011 
DoCreateThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,WaitStatus & ret)1012 bool IThumbnailHelper::DoCreateThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, WaitStatus &ret)
1013 {
1014     MEDIA_INFO_LOG("Start DoCreateThumbnail, id: %{public}s, path: %{public}s",
1015         data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
1016     int64_t startTime = MediaFileUtils::UTCTimeMilliSeconds();
1017     ThumbnailWait thumbnailWait(true);
1018     ret = thumbnailWait.InsertAndWait(data.id, ThumbnailType::THUMB, data.dateModified);
1019     data.needCheckWaitStatus = true;
1020     if (ret != WaitStatus::INSERT && ret != WaitStatus::WAIT_CONTINUE) {
1021         return ret == WaitStatus::WAIT_SUCCESS;
1022     }
1023 
1024     if (!IsCreateThumbnailSuccess(opts, data)) {
1025         MEDIA_ERR_LOG("Fail to create thumbnail, path: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
1026         return false;
1027     }
1028 
1029     if (data.orientation != 0 && !IsCreateThumbnailExSuccess(opts, data)) {
1030         MEDIA_ERR_LOG("Fail to create thumbnailEx, path: %{public}s", DfxUtils::GetSafePath(opts.path).c_str());
1031     }
1032     thumbnailWait.UpdateThumbnailMap();
1033     data.needCheckWaitStatus = false;
1034     MediaLibraryAstcStat::GetInstance().AddAstcInfo(startTime, data.stats.scene,
1035         AstcGenScene::SCREEN_ON, data.id);
1036     return true;
1037 }
1038 
IsCreateThumbnailSuccess(ThumbRdbOpt & opts,ThumbnailData & data)1039 bool IThumbnailHelper::IsCreateThumbnailSuccess(ThumbRdbOpt &opts, ThumbnailData &data)
1040 {
1041     data.loaderOpts.decodeInThumbSize = true;
1042     if (!TryLoadSource(opts, data)) {
1043         MEDIA_ERR_LOG("DoCreateThumbnail failed, try to load source failed, id: %{public}s", data.id.c_str());
1044         return false;
1045     }
1046     auto pixelMap = data.source.GetPixelMap();
1047     if (pixelMap != nullptr && pixelMap->IsHdr()) {
1048         uint32_t ret = pixelMap->ToSdr();
1049         if (ret != E_OK) {
1050             MEDIA_ERR_LOG("DoCreateThumbnail failed to transform to sdr, id: %{public}s.", data.id.c_str());
1051             return false;
1052         }
1053     }
1054     if (!GenThumbnail(opts, data, ThumbnailType::THUMB)) {
1055         return false;
1056     }
1057     if (opts.table == AudioColumn::AUDIOS_TABLE) {
1058         MEDIA_DEBUG_LOG("AUDIOS_TABLE, no need to create all thumbnail");
1059         return true;
1060     }
1061 
1062     if (ThumbnailUtils::IsSupportGenAstc() && !GenThumbnail(opts, data, ThumbnailType::THUMB_ASTC)) {
1063         return false;
1064     }
1065 
1066     if (!data.tracks.empty()) {
1067         MEDIA_INFO_LOG("generate highlight frame, no need to create month and year astc");
1068         return true;
1069     }
1070 
1071     // for some device that do not support KvStore, no need to generate the month and year astc.
1072     if (MediaLibraryKvStoreManager::GetInstance()
1073         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC) == nullptr) {
1074         MEDIA_DEBUG_LOG("kvStore is nullptr, no need to create month and year astc");
1075         return true;
1076     }
1077     if (!GenThumbnail(opts, data, ThumbnailType::MTH_ASTC)) {
1078         return false;
1079     }
1080     if (!GenThumbnail(opts, data, ThumbnailType::YEAR_ASTC)) {
1081         return false;
1082     }
1083     return true;
1084 }
1085 
IsCreateThumbnailExSuccess(ThumbRdbOpt & opts,ThumbnailData & data)1086 bool IThumbnailHelper::IsCreateThumbnailExSuccess(ThumbRdbOpt &opts, ThumbnailData &data)
1087 {
1088     if (!GenThumbnailEx(opts, data)) {
1089         MEDIA_ERR_LOG("Fail to create thumbnailEx, fileName: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1090         return false;
1091     }
1092     return true;
1093 }
1094 
DoRotateThumbnail(ThumbRdbOpt & opts,ThumbnailData & data)1095 bool IThumbnailHelper::DoRotateThumbnail(ThumbRdbOpt &opts, ThumbnailData &data)
1096 {
1097     auto pixelMap = data.source.GetPixelMap();
1098     if (pixelMap == nullptr) {
1099         MEDIA_ERR_LOG("source is nullptr when rotate thumbnail path: %{public}s",
1100             DfxUtils::GetSafePath(data.path).c_str());
1101         return false;
1102     }
1103 
1104     if (!ThumbnailUtils::CompressImage(pixelMap, data.thumbnail, false)) {
1105         MEDIA_ERR_LOG("CompressImage faild id %{public}s", data.id.c_str());
1106         return false;
1107     }
1108 
1109     if (!TrySavePixelMap(data, ThumbnailType::THUMB)) {
1110         MEDIA_ERR_LOG("DoRotateThumbnail failed: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1111         return false;
1112     }
1113     data.thumbnail.clear();
1114     return true;
1115 }
1116 
ScaleLcdToThumbnail(ThumbnailData & data)1117 static bool ScaleLcdToThumbnail(ThumbnailData &data)
1118 {
1119     if (data.source.IsEmptySource()) {
1120         MEDIA_ERR_LOG("data source is empty when scaling from lcd to thumb");
1121         return false;
1122     }
1123 
1124     data.loaderOpts.decodeInThumbSize = true;
1125     if (data.source.HasPictureSource()) {
1126         MEDIA_INFO_LOG("Scale from picture source, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1127         auto mainPixelMap = data.source.GetPicture()->GetMainPixel();
1128         data.source.SetPixelMap(mainPixelMap);
1129     }
1130     if (!ThumbnailUtils::ScaleThumbnailFromSource(data, false)) {
1131         MEDIA_ERR_LOG("Fail to scale from LCD to THM, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1132         return false;
1133     }
1134 
1135     if (data.orientation != 0 && data.source.HasPictureSource()) {
1136         MEDIA_INFO_LOG("Scale from picture source, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1137         auto mainPixelMapEx = data.source.GetPictureEx()->GetMainPixel();
1138         data.source.SetPixelMapEx(mainPixelMapEx);
1139     }
1140     if (data.orientation != 0 && !ThumbnailUtils::ScaleThumbnailFromSource(data, true)) {
1141         MEDIA_ERR_LOG("Fail to scale from LCD_EX to THM_EX, path: %{public}s",
1142             DfxUtils::GetSafePath(data.path).c_str());
1143     }
1144     return true;
1145 }
1146 
DoCreateLcdAndThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,WaitStatus & ret)1147 bool IThumbnailHelper::DoCreateLcdAndThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, WaitStatus &ret)
1148 {
1149     MEDIA_INFO_LOG("Start DoCreateLcdAndThumbnail, id: %{public}s, path: %{public}s",
1150         data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
1151     data.isNeedStoreSize = false;
1152     DoCreateLcd(opts, data, ret);
1153     ScaleLcdToThumbnail(data);
1154     return DoCreateThumbnail(opts, data, ret);
1155 }
1156 
GetAvailableThumbnailSuffix(ThumbnailData & data)1157 std::string GetAvailableThumbnailSuffix(ThumbnailData &data)
1158 {
1159     // Check whether the thumbnail data exist, firstly thumb then lcd, and return the corresponding suffix.
1160     // When there is no thumbnail data, return empty string.
1161     if (access(GetThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX).c_str(), F_OK) == 0) {
1162         return THUMBNAIL_THUMB_SUFFIX;
1163     }
1164     if (access(GetThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX).c_str(), F_OK) == 0) {
1165         return THUMBNAIL_LCD_SUFFIX;
1166     }
1167     return "";
1168 }
1169 
DoCreateAstc(ThumbRdbOpt & opts,ThumbnailData & data)1170 bool IThumbnailHelper::DoCreateAstc(ThumbRdbOpt &opts, ThumbnailData &data)
1171 {
1172     MEDIA_INFO_LOG("Start DoCreateAstc, id: %{public}s, path: %{public}s",
1173         data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
1174     data.loaderOpts.decodeInThumbSize = true;
1175     if (!TryLoadSource(opts, data)) {
1176         MEDIA_ERR_LOG("DoCreateAstc failed, try to load exist thumbnail failed, id: %{public}s", data.id.c_str());
1177         return false;
1178     }
1179     auto pixelMap = data.source.GetPixelMap();
1180     if (pixelMap != nullptr && pixelMap->IsHdr()) {
1181         uint32_t ret = pixelMap->ToSdr();
1182         if (ret != E_OK) {
1183             MEDIA_ERR_LOG("DoCreateAstc failed to transform to sdr, id: %{public}s.", data.id.c_str());
1184             return false;
1185         }
1186     }
1187     if (!GenThumbnail(opts, data, ThumbnailType::THUMB)) {
1188         MEDIA_ERR_LOG("DoCreateAstc GenThumbnail THUMB failed, id: %{public}s", data.id.c_str());
1189         return false;
1190     }
1191     if (!GenThumbnail(opts, data, ThumbnailType::THUMB_ASTC)) {
1192         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
1193             {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN}, {KEY_OPT_FILE, opts.path}, {KEY_OPT_TYPE, OptType::THUMB}};
1194         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1195         return false;
1196     }
1197     if (!GenThumbnail(opts, data, ThumbnailType::MTH_ASTC) || !GenThumbnail(opts, data, ThumbnailType::YEAR_ASTC)) {
1198         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
1199             {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN}, {KEY_OPT_FILE, opts.path}, {KEY_OPT_TYPE, OptType::THUMB}};
1200         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1201         return false;
1202     }
1203     return true;
1204 }
1205 
DoCreateAstcMthAndYear(ThumbRdbOpt & opts,ThumbnailData & data)1206 bool IThumbnailHelper::DoCreateAstcMthAndYear(ThumbRdbOpt &opts, ThumbnailData &data)
1207 {
1208     MEDIA_INFO_LOG("Start DoCreateAstcMthAndYear, id: %{public}s, path: %{public}s",
1209         data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
1210     data.loaderOpts.decodeInThumbSize = true;
1211     data.loaderOpts.desiredType = ThumbnailType::MTH_ASTC;
1212     if (!TryLoadSource(opts, data)) {
1213         MEDIA_ERR_LOG("DoCreateAstcMthAndYear failed, try load source failed, id: %{public}s", data.id.c_str());
1214         return false;
1215     }
1216     auto pixelMap = data.source.GetPixelMap();
1217     if (pixelMap == nullptr) {
1218         MEDIA_ERR_LOG("DoCreateAstc failed, no available pixelMap, id: %{public}s.", data.id.c_str());
1219         return false;
1220     }
1221     if (!GenThumbnail(opts, data, ThumbnailType::MTH_ASTC) || !GenThumbnail(opts, data, ThumbnailType::YEAR_ASTC)) {
1222         MEDIA_ERR_LOG("DoCreateAstc failed, GenThumbnail failed, id: %{public}s.", data.id.c_str());
1223         return false;
1224     }
1225     return true;
1226 }
1227 
GenerateRotatedThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType)1228 bool GenerateRotatedThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, ThumbnailType thumbType)
1229 {
1230     WaitStatus status;
1231     if (thumbType == ThumbnailType::LCD && !IThumbnailHelper::DoCreateLcd(opts, data, status)) {
1232         MEDIA_ERR_LOG("Get lcd thumbnail pixelmap, rotate lcd failed: %{public}s",
1233             DfxUtils::GetSafePath(data.path).c_str());
1234         return false;
1235     }
1236     if (thumbType != ThumbnailType::LCD && !IThumbnailHelper::DoRotateThumbnail(opts, data)) {
1237         MEDIA_ERR_LOG("Get default thumbnail pixelmap, rotate thumbnail failed: %{public}s",
1238             DfxUtils::GetSafePath(data.path).c_str());
1239         return false;
1240     }
1241     return true;
1242 }
1243 
DecodeThumbnailFromFd(int32_t fd)1244 unique_ptr<PixelMap> DecodeThumbnailFromFd(int32_t fd)
1245 {
1246     SourceOptions opts;
1247     uint32_t err = 0;
1248     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(fd, opts, err);
1249     if (imageSource == nullptr) {
1250         MEDIA_ERR_LOG("Decode thumbnail from fd failed, CreateImageSource err: %{public}d", err);
1251         return nullptr;
1252     }
1253 
1254     ImageInfo imageInfo;
1255     err = imageSource->GetImageInfo(0, imageInfo);
1256     if (err != E_OK) {
1257         MEDIA_ERR_LOG("Decode thumbnail from fd failed, GetImageInfo err: %{public}d", err);
1258         return nullptr;
1259     }
1260 
1261     DecodeOptions decodeOpts;
1262     decodeOpts.desiredDynamicRange = DecodeDynamicRange::SDR;
1263     decodeOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
1264     unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
1265     if (pixelMap == nullptr) {
1266         MEDIA_ERR_LOG("Decode thumbnail from fd failed, CreatePixelMap err: %{public}d", err);
1267         return nullptr;
1268     }
1269     return pixelMap;
1270 }
1271 
DoCreateAstcEx(ThumbRdbOpt & opts,ThumbnailData & data,WaitStatus & ret)1272 bool IThumbnailHelper::DoCreateAstcEx(ThumbRdbOpt &opts, ThumbnailData &data, WaitStatus &ret)
1273 {
1274     ThumbnailWait thumbnailWait(true);
1275     ret = thumbnailWait.CloudInsertAndWait(data.id, CloudLoadType::CLOUD_DOWNLOAD);
1276     if (ret != WaitStatus::INSERT && ret != WaitStatus::WAIT_CONTINUE) {
1277         return ret == WaitStatus::WAIT_SUCCESS;
1278     }
1279 
1280     MEDIA_INFO_LOG("Start DoCreateAstcEx, id: %{public}s, path: %{public}s",
1281         data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
1282     string fileName = GetThumbnailPath(data.path, THUMBNAIL_LCD_EX_SUFFIX);
1283     if (access(fileName.c_str(), F_OK) != 0) {
1284         MEDIA_ERR_LOG("No available file in THM_EX, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1285         return false;
1286     }
1287 
1288     if (!DoCreateLcd(opts, data, ret)) {
1289         MEDIA_ERR_LOG("Fail to create lcd, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1290         return false;
1291     }
1292 
1293     data.loaderOpts.decodeInThumbSize = true;
1294     if (data.source.HasPictureSource()) {
1295         MEDIA_INFO_LOG("Scale from picture source, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1296         auto mainPixelMap = data.source.GetPicture()->GetMainPixel();
1297         data.source.SetPixelMap(mainPixelMap);
1298     }
1299     if (!ThumbnailUtils::ScaleThumbnailFromSource(data, false)) {
1300         MEDIA_ERR_LOG("Fail to scale from LCD to THM, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1301         return false;
1302     }
1303     if (!DoCreateThumbnail(opts, data, ret)) {
1304         MEDIA_ERR_LOG("Fail to create thumbnail, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1305         return false;
1306     }
1307 
1308     thumbnailWait.UpdateCloudLoadThumbnailMap(CloudLoadType::CLOUD_DOWNLOAD, true);
1309     return true;
1310 }
1311 
DoRotateThumbnailEx(ThumbRdbOpt & opts,ThumbnailData & data,int32_t fd,ThumbnailType thumbType)1312 bool IThumbnailHelper::DoRotateThumbnailEx(ThumbRdbOpt &opts, ThumbnailData &data, int32_t fd, ThumbnailType thumbType)
1313 {
1314     ThumbnailWait thumbnailWait(true);
1315     auto ret = thumbnailWait.CloudInsertAndWait(data.id, thumbType == ThumbnailType::LCD ?
1316         CloudLoadType::CLOUD_READ_LCD : CloudLoadType::CLOUD_READ_THUMB);
1317     if (ret != WaitStatus::INSERT && ret != WaitStatus::WAIT_CONTINUE) {
1318         close(fd);
1319         return ret == WaitStatus::WAIT_SUCCESS;
1320     }
1321 
1322     auto dataSourcePtr = DecodeThumbnailFromFd(fd);
1323     std::shared_ptr<PixelMap> dataSource = std::move(dataSourcePtr);
1324     if (dataSource == nullptr) {
1325         MEDIA_ERR_LOG("GetThumbnailPixelMap failed, dataSource is nullptr, path: %{public}s",
1326             DfxUtils::GetSafePath(data.path).c_str());
1327         close(fd);
1328         thumbnailWait.UpdateCloudLoadThumbnailMap(thumbType == ThumbnailType::LCD ?
1329             CloudLoadType::CLOUD_READ_LCD : CloudLoadType::CLOUD_READ_THUMB, false);
1330         return false;
1331     }
1332     close(fd);
1333 
1334     PostProc::RotateInRectangularSteps(*(dataSource.get()), static_cast<float>(data.orientation), true);
1335     data.source.SetPixelMap(dataSource);
1336     if (!GenerateRotatedThumbnail(opts, data, thumbType)) {
1337         MEDIA_ERR_LOG("GenerateRotatedThumbnail failed, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
1338         thumbnailWait.UpdateCloudLoadThumbnailMap(thumbType == ThumbnailType::LCD ?
1339             CloudLoadType::CLOUD_READ_LCD : CloudLoadType::CLOUD_READ_THUMB, false);
1340         return false;
1341     }
1342 
1343     thumbnailWait.UpdateCloudLoadThumbnailMap(thumbType == ThumbnailType::LCD ?
1344         CloudLoadType::CLOUD_READ_LCD : CloudLoadType::CLOUD_READ_THUMB, true);
1345     return true;
1346 }
1347 
IsPureCloudImage(ThumbRdbOpt & opts)1348 bool IThumbnailHelper::IsPureCloudImage(ThumbRdbOpt &opts)
1349 {
1350     vector<string> columns = {
1351         MEDIA_DATA_DB_ID,
1352         PhotoColumn::PHOTO_POSITION
1353     };
1354     if (opts.row.empty() || opts.table.empty()) {
1355         MEDIA_ERR_LOG("IsPureCloudImage opts.row is empty");
1356         return false;
1357     }
1358     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + opts.row;
1359     RdbPredicates rdbPredicates(opts.table);
1360     rdbPredicates.SetWhereClause(strQueryCondition);
1361     if (opts.store == nullptr) {
1362         MEDIA_ERR_LOG("IsPureCloudImage opts.store is nullptr");
1363         return false;
1364     }
1365     auto resultSet = opts.store->QueryByStep(rdbPredicates, columns);
1366     if (resultSet == nullptr) {
1367         MEDIA_ERR_LOG("IsPureCloudImage result set is null");
1368         return false;
1369     }
1370     auto ret = resultSet->GoToFirstRow();
1371     if (ret != NativeRdb::E_OK) {
1372         MEDIA_ERR_LOG("IsPureCloudImage go to first row failed");
1373         return false;
1374     }
1375     int photoPosition = GetInt32Val(PhotoColumn::PHOTO_POSITION, resultSet);
1376 
1377     // if current image is a pure cloud image, it's photo position column in database will be 2
1378     return photoPosition == 2;
1379 }
1380 } // namespace Media
1381 } // namespace OHOS