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