• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "thumbnail_generate_helper.h"
18 
19 #include <fcntl.h>
20 
21 #include "acl.h"
22 #include "cloud_sync_helper.h"
23 #include "dfx_const.h"
24 #include "dfx_manager.h"
25 #include "dfx_timer.h"
26 #include "dfx_utils.h"
27 #include "ffrt.h"
28 #include "ffrt_inner.h"
29 #include "directory_ex.h"
30 #include "ithumbnail_helper.h"
31 #include "medialibrary_bundle_manager.h"
32 #include "medialibrary_errno.h"
33 #include "medialibrary_kvstore_manager.h"
34 #include "medialibrary_photo_operations.h"
35 #include "medialibrary_type_const.h"
36 #include "media_file_utils.h"
37 #include "media_image_framework_utils.h"
38 #include "media_log.h"
39 #include "media_player_framework_utils.h"
40 #include "thumbnail_const.h"
41 #include "thumbnail_file_utils.h"
42 #include "thumbnail_generate_worker_manager.h"
43 #include "thumbnail_generation_post_process.h"
44 #include "thumbnail_rdb_utils.h"
45 #include "thumbnail_source_loading.h"
46 #include "thumbnail_utils.h"
47 #include "highlight_column.h"
48 
49 using namespace std;
50 using namespace OHOS::DistributedKv;
51 using namespace OHOS::NativeRdb;
52 
53 namespace OHOS {
54 namespace Media {
55 const int FFRT_MAX_RESTORE_ASTC_THREADS = 4;
56 const std::string SQL_REFRESH_THUMBNAIL_READY =
57     " Update " + PhotoColumn::PHOTOS_TABLE + " SET " + PhotoColumn::PHOTO_THUMBNAIL_READY + " = 7 " +
58     " WHERE " + PhotoColumn::PHOTO_THUMBNAIL_READY + " != 0; END;";
59 
CreateThumbnailFileScaned(ThumbRdbOpt & opts,bool isSync)60 int32_t ThumbnailGenerateHelper::CreateThumbnailFileScaned(ThumbRdbOpt &opts, bool isSync)
61 {
62     ThumbnailData thumbnailData;
63     ThumbnailUtils::GetThumbnailInfo(opts, thumbnailData);
64     thumbnailData.needResizeLcd = true;
65     thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
66     ThumbnailUtils::RecordStartGenerateStats(thumbnailData.stats, GenerateScene::LOCAL, LoadSourceType::LOCAL_PHOTO);
67     MEDIA_INFO_LOG("Delete THM_EX directory successsfully:%{public}d, id: %{public}s, path: %{public}s",
68         ThumbnailFileUtils::DeleteThumbExDir(thumbnailData), thumbnailData.id.c_str(),
69         DfxUtils::GetSafePath(thumbnailData.path).c_str());
70 
71     if (isSync) {
72         IThumbnailHelper::DoCreateLcdAndThumbnail(opts, thumbnailData);
73         int32_t err = ThumbnailGenerationPostProcess::PostProcess(thumbnailData, opts);
74         CHECK_AND_PRINT_LOG(err == E_OK, "PostProcess failed! err %{public}d", err);
75         ThumbnailUtils::RecordCostTimeAndReport(thumbnailData.stats);
76     } else {
77         IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
78             opts, thumbnailData, ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::HIGH);
79     }
80     return E_OK;
81 }
82 
CreateThumbnailFileScanedWithPicture(ThumbRdbOpt & opts,std::shared_ptr<Picture> originalPhotoPicture,bool isSync)83 int32_t ThumbnailGenerateHelper::CreateThumbnailFileScanedWithPicture(ThumbRdbOpt &opts,
84     std::shared_ptr<Picture> originalPhotoPicture, bool isSync)
85 {
86     ThumbnailData thumbnailData;
87     ThumbnailUtils::GetThumbnailInfo(opts, thumbnailData);
88     thumbnailData.needResizeLcd = true;
89     thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
90     thumbnailData.originalPhotoPicture = originalPhotoPicture;
91     ThumbnailUtils::RecordStartGenerateStats(thumbnailData.stats, GenerateScene::LOCAL, LoadSourceType::LOCAL_PHOTO);
92     MEDIA_INFO_LOG("Delete THM_EX directory successsfully:%{public}d, originalPhotoPicture exists:%{public}d, "
93         "path: %{public}s, id: %{public}s", ThumbnailFileUtils::DeleteThumbExDir(thumbnailData),
94         originalPhotoPicture != nullptr, DfxUtils::GetSafePath(thumbnailData.path).c_str(), thumbnailData.id.c_str());
95 
96     if (isSync) {
97         IThumbnailHelper::DoCreateLcdAndThumbnail(opts, thumbnailData);
98         int32_t err = ThumbnailGenerationPostProcess::PostProcess(thumbnailData, opts);
99         CHECK_AND_PRINT_LOG(err == E_OK, "PostProcess failed! err %{public}d", err);
100         ThumbnailUtils::RecordCostTimeAndReport(thumbnailData.stats);
101     } else {
102         IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
103             opts, thumbnailData, ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::HIGH);
104     }
105     return E_OK;
106 }
107 
CreateThumbnailBackground(ThumbRdbOpt & opts)108 int32_t ThumbnailGenerateHelper::CreateThumbnailBackground(ThumbRdbOpt &opts)
109 {
110     if (opts.store == nullptr) {
111         MEDIA_ERR_LOG("rdbStore is not init");
112         return E_ERR;
113     }
114     CHECK_AND_RETURN_RET_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
115         E_FREE_SIZE_NOT_ENOUGH, "Free size is not enough");
116 
117     vector<ThumbnailData> infos;
118     int32_t err = GetNoThumbnailData(opts, infos);
119     if (err != E_OK) {
120         MEDIA_ERR_LOG("Failed to GetNoLThumbnailData %{private}d", err);
121         return err;
122     }
123 
124     if (infos.empty()) {
125         MEDIA_DEBUG_LOG("No need generate thumbnail.");
126         return E_OK;
127     }
128     auto createThumbnailBackgroundTask = [](std::shared_ptr<ThumbnailTaskData> &data) {
129         CHECK_AND_RETURN_LOG(data != nullptr, "Data is null");
130         auto &thumbnailData = data->thumbnailData_;
131         CHECK_AND_RETURN_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
132             "CreateThumbnailBackgroundTask free size is not enough, id:%{public}s, path:%{public}s",
133             thumbnailData.id.c_str(), DfxUtils::GetSafePath(thumbnailData.path).c_str());
134         IThumbnailHelper::CreateThumbnail(data);
135     };
136 
137     for (uint32_t i = 0; i < infos.size(); i++) {
138         opts.row = infos[i].id;
139         infos[i].loaderOpts.loadingStates = infos[i].isLocalFile ? SourceLoader::LOCAL_SOURCE_LOADING_STATES :
140             SourceLoader::CLOUD_SOURCE_LOADING_STATES;
141         IThumbnailHelper::AddThumbnailGenerateTask(createThumbnailBackgroundTask,
142             opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
143     }
144 
145     return E_OK;
146 }
147 
CreateAstcBackgroundTask(std::shared_ptr<ThumbnailTaskData> & data)148 void CreateAstcBackgroundTask(std::shared_ptr<ThumbnailTaskData> &data)
149 {
150     CHECK_AND_RETURN_LOG(data != nullptr, "Data is null");
151     auto &thumbnailData = data->thumbnailData_;
152     CHECK_AND_RETURN_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
153         "CreateAstcBackgroundTask free size is not enough, id:%{public}s, path:%{public}s",
154         thumbnailData.id.c_str(), DfxUtils::GetSafePath(thumbnailData.path).c_str());
155     if (thumbnailData.isLocalFile) {
156         thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
157         IThumbnailHelper::CreateThumbnail(data);
158     } else {
159         thumbnailData.needGenerateExThumbnail = false;
160         ThumbnailUtils::HandleImageExifRotate(thumbnailData);
161         thumbnailData.loaderOpts.loadingStates = ThumbnailUtils::IsExCloudThumbnail(thumbnailData) ?
162             SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES : SourceLoader::CLOUD_SOURCE_LOADING_STATES;
163         ThumbnailUtils::IsExCloudThumbnail(thumbnailData) ?
164             IThumbnailHelper::CreateAstcEx(data) : IThumbnailHelper::CreateAstc(data);
165     }
166 }
167 
CreateAstcBackground(ThumbRdbOpt & opts)168 int32_t ThumbnailGenerateHelper::CreateAstcBackground(ThumbRdbOpt &opts)
169 {
170     if (opts.store == nullptr) {
171         MEDIA_ERR_LOG("rdbStore is not init");
172         return E_ERR;
173     }
174 
175     CheckMonthAndYearKvStoreValid(opts);
176     CHECK_AND_RETURN_RET_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
177         E_FREE_SIZE_NOT_ENOUGH, "Free size is not enough");
178     vector<ThumbnailData> infos;
179     int32_t err = GetNoAstcData(opts, infos);
180     if (err != E_OK) {
181         MEDIA_ERR_LOG("Failed to GetNoAstcData %{private}d", err);
182         return err;
183     }
184 
185     auto kvStore = MediaLibraryKvStoreManager::GetInstance()
186         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
187     if (infos.empty() || kvStore == nullptr) {
188         MEDIA_DEBUG_LOG("No need create Astc.");
189         return E_OK;
190     }
191 
192     MEDIA_INFO_LOG("no astc data size: %{public}d", static_cast<int>(infos.size()));
193     for (uint32_t i = 0; i < infos.size(); i++) {
194         opts.row = infos[i].id;
195         ThumbnailUtils::RecordStartGenerateStats(infos[i].stats, GenerateScene::BACKGROUND,
196             LoadSourceType::LOCAL_PHOTO);
197         IThumbnailHelper::AddThumbnailGenerateTask(CreateAstcBackgroundTask,
198             opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
199     }
200     return E_OK;
201 }
202 
CreateAstcCloudDownload(ThumbRdbOpt & opts,bool isCloudInsertTaskPriorityHigh)203 int32_t ThumbnailGenerateHelper::CreateAstcCloudDownload(ThumbRdbOpt &opts, bool isCloudInsertTaskPriorityHigh)
204 {
205     ThumbnailData data;
206     ThumbnailUtils::RecordStartGenerateStats(data.stats, GenerateScene::CLOUD, LoadSourceType::LOCAL_PHOTO);
207     int err = 0;
208     ThumbnailUtils::QueryThumbnailDataFromFileId(opts, opts.fileId, data, err);
209     ThumbnailUtils::HandleImageExifRotate(data);
210     if (err != E_OK) {
211         MEDIA_ERR_LOG("QueryThumbnailDataFromFileId failed, path: %{public}s",
212             DfxUtils::GetSafePath(data.path).c_str());
213         return err;
214     }
215     ValuesBucket values;
216     Size lcdSize;
217     if (data.mediaType == MEDIA_TYPE_VIDEO && ThumbnailUtils::GetLocalThumbSize(data, ThumbnailType::LCD, lcdSize)) {
218         ThumbnailUtils::SetThumbnailSizeValue(values, lcdSize, PhotoColumn::PHOTO_LCD_SIZE);
219         int changedRows;
220         int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
221         vector<string> { data.id });
222         CHECK_AND_PRINT_LOG(err == NativeRdb::E_OK, "RdbStore lcd size failed! %{public}d", err);
223     }
224 
225     data.needGenerateExThumbnail = false;
226     data.loaderOpts.loadingStates = ThumbnailUtils::IsExCloudThumbnail(data) ?
227         SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES : SourceLoader::CLOUD_SOURCE_LOADING_STATES;
228     if (isCloudInsertTaskPriorityHigh) {
229         IThumbnailHelper::AddThumbnailGenerateTask(ThumbnailUtils::IsExCloudThumbnail(data) ?
230             IThumbnailHelper::CreateAstcEx : IThumbnailHelper::CreateAstc,
231             opts, data, ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::MID);
232         return E_OK;
233     }
234 
235     auto lowPriorityCreateAstcCloudDownloadTask = [](std::shared_ptr<ThumbnailTaskData> &data) {
236         CHECK_AND_RETURN_LOG(data != nullptr, "Data is null");
237         auto &thumbnailData = data->thumbnailData_;
238         CHECK_AND_RETURN_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
239             "LowPriorityCreateAstcCloudDownloadTask free size is not enough, id:%{public}s, path:%{public}s",
240             thumbnailData.id.c_str(), DfxUtils::GetSafePath(thumbnailData.path).c_str());
241         ThumbnailUtils::IsExCloudThumbnail(thumbnailData) ?
242             IThumbnailHelper::CreateAstcEx(data) : IThumbnailHelper::CreateAstc(data);
243     };
244     IThumbnailHelper::AddThumbnailGenerateTask(lowPriorityCreateAstcCloudDownloadTask,
245         opts, data, ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
246     return E_OK;
247 }
248 
RegenerateThumbnailFromCloud(ThumbRdbOpt & opts)249 int32_t ThumbnailGenerateHelper::RegenerateThumbnailFromCloud(ThumbRdbOpt &opts)
250 {
251     ThumbnailData data;
252     int err = 0;
253     ThumbnailUtils::QueryThumbnailDataFromFileId(opts, opts.fileId, data, err);
254     if (err != E_OK) {
255         MEDIA_ERR_LOG("Query data from fileId failed, path: %{public}s",
256             DfxUtils::GetSafePath(data.path).c_str());
257         return err;
258     }
259     if (data.dirty != static_cast<int32_t>(DirtyType::TYPE_SYNCED)) {
260         MEDIA_ERR_LOG("Not synced data, RegenerateThumbnailFromCloud cancelled, path: %{public}s",
261             DfxUtils::GetSafePath(data.path).c_str());
262         return err;
263     }
264 
265     opts.row = data.id;
266     data.isRegenerateStage = true;
267     data.createLowQulityLcd = true;
268     data.loaderOpts.loadingStates = SourceLoader::CLOUD_ORIGIN_SOURCE_LOADING_STATES;
269     CHECK_AND_EXECUTE(data.isLocalFile, ThumbnailUtils::HandleImageExifRotate(data));
270     IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
271         opts, data, ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
272     return E_OK;
273 }
274 
CreateAstcMthAndYear(ThumbRdbOpt & opts)275 int32_t ThumbnailGenerateHelper::CreateAstcMthAndYear(ThumbRdbOpt &opts)
276 {
277     ThumbnailData data;
278     int err = 0;
279     ThumbnailUtils::QueryThumbnailDataFromFileId(opts, opts.fileId, data, err);
280     if (err != E_OK) {
281         MEDIA_ERR_LOG("CreateAstcMthAndYear query data from fileId failed, id: %{public}s", opts.fileId.c_str());
282         return err;
283     }
284 
285     if (data.isLocalFile) {
286         data.loaderOpts.loadingStates = data.exifRotate == 0 ?
287             SourceLoader::LOCAL_SOURCE_LOADING_STATES : SourceLoader::LOCAL_THUMB_SOURCE_LOADING_STATES;
288     } else {
289         ThumbnailUtils::HandleImageExifRotate(data);
290         data.loaderOpts.loadingStates = SourceLoader::CLOUD_SOURCE_LOADING_STATES;
291     }
292     data.needGenerateExThumbnail = false;
293     if (!IThumbnailHelper::DoCreateAstcMthAndYear(opts, data)) {
294         return E_ERR;
295     }
296     return E_OK;
297 }
298 
CreateLocalThumbnail(ThumbRdbOpt & opts)299 int32_t ThumbnailGenerateHelper::CreateLocalThumbnail(ThumbRdbOpt &opts)
300 {
301     if (opts.store == nullptr) {
302         MEDIA_ERR_LOG("rdbStore is not init");
303         return E_ERR;
304     }
305     vector<ThumbnailData> infos;
306     int32_t err = 0;
307     if (!ThumbnailUtils::QueryLocalNoThumbnailInfos(opts, infos, err)) {
308         MEDIA_ERR_LOG("Failed to QueryNoThumbnailInfos %{private}d", err);
309         IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CloudSyncOnGenerationComplete,
310             ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::MID);
311         return err;
312     }
313     if (infos.empty()) {
314         IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CloudSyncOnGenerationComplete,
315             ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::MID);
316         return E_OK;
317     }
318     std::shared_ptr<ExecuteParamBuilder> param = std::make_shared<ExecuteParamBuilder>();
319     param->batteryLimit_ = LOCAL_GENERATION_BATTERY_CAPACITY;
320     param->tempLimit_ = READY_TEMPERATURE_LEVEL;
321     param->affinity_ = CpuAffinityType::CPU_IDX_6;
322     MEDIA_INFO_LOG("CreateLocalThumbnail: %{public}d", static_cast<int>(infos.size()));
323     for (uint32_t i = 0; i < infos.size(); i++) {
324         opts.row = infos[i].id;
325         infos[i].loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
326         if (infos[i].thumbnailReady == 0 && infos[i].lcdVisitTime == 0) {
327             IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
328                 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::MID, param);
329         } else if (infos[i].thumbnailReady == 0) {
330             IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateThumbnail,
331                 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::MID, param);
332         } else if (infos[i].lcdVisitTime == 0) {
333             IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcd,
334                 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::MID, param);
335         }
336     }
337     IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CloudSyncOnGenerationComplete,
338         ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::MID);
339     return E_OK;
340 }
341 
CreateAstcBatchOnDemand(ThumbRdbOpt & opts,NativeRdb::RdbPredicates & predicate,int32_t requestId)342 int32_t ThumbnailGenerateHelper::CreateAstcBatchOnDemand(
343     ThumbRdbOpt &opts, NativeRdb::RdbPredicates &predicate, int32_t requestId)
344 {
345     if (opts.store == nullptr) {
346         MEDIA_ERR_LOG("rdbStore is not init");
347         return E_ERR;
348     }
349 
350     vector<ThumbnailData> infos;
351     int32_t err = 0;
352     if (!ThumbnailUtils::QueryNoAstcInfosOnDemand(opts, infos, predicate, err)) {
353         MEDIA_ERR_LOG("Failed to QueryNoAstcInfos %{public}d", err);
354         return err;
355     }
356     if (infos.empty()) {
357         MEDIA_INFO_LOG("No need create Astc.");
358         return E_THUMBNAIL_ASTC_ALL_EXIST;
359     }
360 
361     MEDIA_INFO_LOG("no astc data size: %{public}d, requestId: %{public}d", static_cast<int>(infos.size()), requestId);
362     for (auto& info : infos) {
363         opts.row = info.id;
364         ThumbnailUtils::RecordStartGenerateStats(info.stats, GenerateScene::FOREGROUND, LoadSourceType::LOCAL_PHOTO);
365         if (info.isLocalFile) {
366             info.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
367             IThumbnailHelper::AddThumbnailGenBatchTask(IThumbnailHelper::CreateThumbnail, opts, info, requestId);
368             continue;
369         }
370 
371         info.needGenerateExThumbnail = false;
372         ThumbnailUtils::HandleImageExifRotate(info);
373         if (ThumbnailUtils::IsExCloudThumbnail(info)) {
374             info.loaderOpts.loadingStates = SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES;
375             IThumbnailHelper::AddThumbnailGenBatchTask(IThumbnailHelper::CreateAstcEx, opts, info, requestId);
376         } else {
377             info.loaderOpts.loadingStates = info.mediaType == MEDIA_TYPE_VIDEO ?
378                 SourceLoader::ALL_SOURCE_LOADING_CLOUD_VIDEO_STATES : SourceLoader::ALL_SOURCE_LOADING_STATES;
379             IThumbnailHelper::AddThumbnailGenBatchTask(IThumbnailHelper::CreateAstc, opts, info, requestId);
380         }
381     }
382     return E_OK;
383 }
384 
NeedGenerateLocalLcd(ThumbnailData & data)385 bool NeedGenerateLocalLcd(ThumbnailData &data)
386 {
387     std::string lcdLocalPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
388     size_t lcdSize = -1;
389 
390     // Local LCD exist, and its size is less than upload limit
391     if (access(lcdLocalPath.c_str(), F_OK) == 0 && MediaFileUtils::GetFileSize(lcdLocalPath, lcdSize) &&
392         lcdSize < LCD_UPLOAD_LIMIT_SIZE) {
393         return false;
394     }
395     MEDIA_INFO_LOG("Local file Lcd need to be generate, size: %{public}d, path: %{public}s",
396         static_cast<int>(lcdSize), DfxUtils::GetSafePath(data.path).c_str());
397     return true;
398 }
399 
CreateLcdBackground(ThumbRdbOpt & opts)400 int32_t ThumbnailGenerateHelper::CreateLcdBackground(ThumbRdbOpt &opts)
401 {
402     if (opts.store == nullptr) {
403         return E_ERR;
404     }
405     CHECK_AND_RETURN_RET_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
406         E_FREE_SIZE_NOT_ENOUGH, "Free size is not enough");
407 
408     vector<ThumbnailData> infos;
409     int32_t err = GetNoLcdData(opts, infos);
410     if (err != E_OK) {
411         MEDIA_ERR_LOG("Failed to GetNoLcdData %{private}d", err);
412         return err;
413     }
414     if (infos.empty()) {
415         MEDIA_DEBUG_LOG("No need create Lcd.");
416         return E_THUMBNAIL_LCD_ALL_EXIST;
417     }
418     auto createLcdBackgroundTask = [](std::shared_ptr<ThumbnailTaskData> &data) {
419         CHECK_AND_RETURN_LOG(data != nullptr, "CreateLcd failed, data is null");
420         auto &thumbnailData = data->thumbnailData_;
421         CHECK_AND_RETURN_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
422             "CreateLcdBackgroundTask free size is not enough, id:%{public}s, path:%{public}s",
423             thumbnailData.id.c_str(), DfxUtils::GetSafePath(thumbnailData.path).c_str());
424         thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
425         IThumbnailHelper::CreateLcd(data);
426     };
427 
428     MEDIA_INFO_LOG("No lcd data size: %{public}d", static_cast<int>(infos.size()));
429     for (uint32_t i = 0; i < infos.size(); i++) {
430         opts.row = infos[i].id;
431 
432         // Check whether LCD exists or is over upload limit, if it does, just update the database
433         if (!NeedGenerateLocalLcd(infos[i])) {
434             MEDIA_INFO_LOG("Skip CreateLcdBackground, lcd exists: %{public}s",
435                 DfxUtils::GetSafePath(infos[i].path).c_str());
436             ThumbnailUtils::UpdateLcdReadyStatus(opts, infos[i], err, LcdReady::GENERATE_LCD_COMPLETED);
437             continue;
438         }
439         IThumbnailHelper::AddThumbnailGenerateTask(createLcdBackgroundTask,
440             opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
441     }
442     return E_OK;
443 }
444 
CheckLcdSizeAndUpdateStatus(ThumbRdbOpt & opts)445 int32_t ThumbnailGenerateHelper::CheckLcdSizeAndUpdateStatus(ThumbRdbOpt &opts)
446 {
447     if (opts.store == nullptr) {
448         return E_ERR;
449     }
450 
451     vector<ThumbnailData> infos;
452     int32_t err = GetLocalNoLcdData(opts, infos);
453     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "Failed to CheckLcdSizeAndUpdateStatus %{public}d", err);
454     if (infos.empty()) {
455         MEDIA_INFO_LOG("No need CheckLcdSizeAndUpdateStatus.");
456         return E_THUMBNAIL_LCD_ALL_EXIST;
457     }
458 
459     MEDIA_INFO_LOG("CheckLcdSizeAndUpdateStatus size: %{public}d", static_cast<int>(infos.size()));
460     for (uint32_t i = 0; i < infos.size(); i++) {
461         opts.row = infos[i].id;
462 
463         // Check whether LCD exists or is over upload limit, if it does, just update the database
464         if (!NeedGenerateLocalLcd(infos[i])) {
465             MEDIA_INFO_LOG("Check lcd size succeeded, lcd exists: %{public}s",
466                 DfxUtils::GetSafePath(infos[i].path).c_str());
467             ThumbnailUtils::UpdateLcdReadyStatus(opts, infos[i], err, LcdReady::GENERATE_LCD_COMPLETED);
468         }
469     }
470     return E_OK;
471 }
472 
GetLcdCount(ThumbRdbOpt & opts,int & outLcdCount)473 int32_t ThumbnailGenerateHelper::GetLcdCount(ThumbRdbOpt &opts, int &outLcdCount)
474 {
475     int32_t err = E_ERR;
476     if (!ThumbnailUtils::QueryLcdCount(opts, outLcdCount, err)) {
477         MEDIA_ERR_LOG("Failed to QueryLcdCount %{private}d", err);
478         return err;
479     }
480     return E_OK;
481 }
482 
GetNoLcdData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)483 int32_t ThumbnailGenerateHelper::GetNoLcdData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
484 {
485     int32_t err = E_ERR;
486     if (!ThumbnailUtils::QueryNoLcdInfos(opts, outDatas, err)) {
487         MEDIA_ERR_LOG("Failed to QueryNoLcdInfos %{private}d", err);
488         return err;
489     }
490     return E_OK;
491 }
492 
GetLocalNoLcdData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)493 int32_t ThumbnailGenerateHelper::GetLocalNoLcdData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
494 {
495     int32_t err = E_ERR;
496     if (!ThumbnailUtils::QueryLocalNoLcdInfos(opts, outDatas, err)) {
497         MEDIA_ERR_LOG("Failed to QueryLocalNoLcdInfos %{private}d", err);
498         return err;
499     }
500     return E_OK;
501 }
502 
GetNoThumbnailData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)503 int32_t ThumbnailGenerateHelper::GetNoThumbnailData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
504 {
505     int32_t err = E_ERR;
506     if (!ThumbnailUtils::QueryNoThumbnailInfos(opts, outDatas, err)) {
507         MEDIA_ERR_LOG("Failed to QueryNoThumbnailInfos %{private}d", err);
508         return err;
509     }
510     return E_OK;
511 }
512 
GetNoAstcData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)513 int32_t ThumbnailGenerateHelper::GetNoAstcData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
514 {
515     int32_t err = E_ERR;
516     if (!ThumbnailUtils::QueryNoAstcInfos(opts, outDatas, err)) {
517         MEDIA_ERR_LOG("Failed to QueryNoAstcInfos %{public}d", err);
518         return err;
519     }
520     return E_OK;
521 }
522 
GetNoHighlightData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)523 int32_t ThumbnailGenerateHelper::GetNoHighlightData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
524 {
525     int32_t err = E_ERR;
526     if (!ThumbnailUtils::QueryNoHighlightInfos(opts, outDatas, err)) {
527         MEDIA_ERR_LOG("Failed to QueryNoHighlightInfos %{public}d", err);
528         return err;
529     }
530     return E_OK;
531 }
532 
GetNewThumbnailCount(ThumbRdbOpt & opts,const int64_t & time,int & count)533 int32_t ThumbnailGenerateHelper::GetNewThumbnailCount(ThumbRdbOpt &opts, const int64_t &time, int &count)
534 {
535     int32_t err = E_ERR;
536     if (!ThumbnailUtils::QueryNewThumbnailCount(opts, time, count, err)) {
537         MEDIA_ERR_LOG("Failed to QueryNoThumbnailInfos %{private}d", err);
538         return err;
539     }
540     return E_OK;
541 }
542 
GenerateLocalThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType)543 bool GenerateLocalThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, ThumbnailType thumbType)
544 {
545     data.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
546     if (thumbType == ThumbnailType::LCD) {
547         CHECK_AND_RETURN_RET_LOG(IThumbnailHelper::DoCreateLcd(opts, data), false,
548             "Get default pixelmap, DoCreateLcd failed: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
549     } else {
550         CHECK_AND_RETURN_RET_LOG(IThumbnailHelper::DoCreateThumbnail(opts, data), false,
551             "Get default pixelmap, DoCreateThumbnail failed: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
552     }
553     return true;
554 }
555 
GenerateKeyFrameLocalThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int32_t thumbType)556 bool GenerateKeyFrameLocalThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int32_t thumbType)
557 {
558     data.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
559     if (thumbType == KEY_FRAME_LCD && !IThumbnailHelper::DoCreateLcd(opts, data)) {
560         MEDIA_ERR_LOG("Get key frame lcd thumbnail pixelmap, doCreateLcd failed: %{public}s",
561             DfxUtils::GetSafePath(data.path).c_str());
562         return false;
563     }
564     if (thumbType != KEY_FRAME_LCD) {
565         bool isSuccess = IThumbnailHelper::DoCreateThumbnail(opts, data);
566         if (!isSuccess) {
567             MEDIA_ERR_LOG("Get default key frame thumbnail pixelmap, doCreateThumbnail failed: %{public}s",
568                 DfxUtils::GetSafePath(data.path).c_str());
569             return false;
570         }
571     }
572     return true;
573 }
574 
GetAvailableFile(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType,std::string & fileName)575 int32_t ThumbnailGenerateHelper::GetAvailableFile(ThumbRdbOpt &opts, ThumbnailData &data, ThumbnailType thumbType,
576     std::string &fileName)
577 {
578     fileName = GetAvailablePath(data.path, thumbType);
579     if (access(fileName.c_str(), F_OK) == 0) {
580         // No need to create thumbnails if corresponding file exists
581         MEDIA_INFO_LOG("File exists, path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
582         return E_OK;
583     }
584 
585     // Check if unrotated file exists
586     string fileParentPath = MediaFileUtils::GetParentPath(fileName);
587     string tempFileName = fileParentPath + "/THM_EX" + fileName.substr(fileParentPath.length());
588     if (access(tempFileName.c_str(), F_OK) == 0) {
589         fileName = tempFileName;
590         data.isOpeningCloudFile = true;
591         MEDIA_INFO_LOG("Unrotated file exists, path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
592         return E_OK;
593     }
594 
595     MEDIA_INFO_LOG("No available file, create thumbnail, path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
596     if (!GenerateLocalThumbnail(opts, data, thumbType) && access(fileName.c_str(), F_OK) != 0) {
597         MEDIA_ERR_LOG("GenerateLocalThumbnail failed, path: %{public}s", DfxUtils::GetSafePath(tempFileName).c_str());
598         return E_THUMBNAIL_LOCAL_CREATE_FAIL;
599     }
600 
601     if (!opts.path.empty()) {
602         fileName = GetAvailablePath(data.path, thumbType);
603     }
604     return E_OK;
605 }
606 
GetAvailablePath(const std::string & path,const ThumbnailType & thumbType)607 std::string ThumbnailGenerateHelper::GetAvailablePath(const std::string &path, const ThumbnailType &thumbType)
608 {
609     string thumbSuffix = GetThumbSuffix(thumbType);
610     std::string outputPath = GetThumbnailPath(path, thumbSuffix);
611     if (thumbType == ThumbnailType::THUMB_ASTC) {
612         // Try to get jpeg thumbnail instead if there is no astc file
613         if (access(outputPath.c_str(), F_OK) == 0) {
614             return outputPath;
615         } else {
616             outputPath = GetThumbnailPath(path, GetThumbSuffix(ThumbnailType::THUMB));
617         }
618     }
619     return outputPath;
620 }
621 
GetAvailableKeyFrameFile(ThumbRdbOpt & opts,ThumbnailData & data,int32_t thumbType,std::string & fileName)622 int32_t ThumbnailGenerateHelper::GetAvailableKeyFrameFile(ThumbRdbOpt &opts, ThumbnailData &data, int32_t thumbType,
623     std::string &fileName)
624 {
625     string thumbSuffix = GetKeyFrameThumbSuffix(thumbType);
626     fileName = GetThumbnailPathHighlight(data.path, thumbSuffix, data.timeStamp);
627     // No need to create keyFrame thumbnails if corresponding file exists
628     if (access(fileName.c_str(), F_OK) == 0) {
629         MEDIA_INFO_LOG("GetAvailableKeyFrameFile: file exists, path: %{public}s",
630             DfxUtils::GetSafePath(fileName).c_str());
631         return E_OK;
632     }
633 
634     MEDIA_INFO_LOG("GetAvailableKeyFrameFile: no available file, create thumbnail, path: %{public}s",
635         DfxUtils::GetSafePath(fileName).c_str());
636     if (!GenerateKeyFrameLocalThumbnail(opts, data, thumbType)) {
637         MEDIA_ERR_LOG("GenerateKeyFrameLocalThumbnail failed");
638         return E_THUMBNAIL_LOCAL_CREATE_FAIL;
639     }
640 
641     int32_t err = ThumbnailGenerationPostProcess::PostProcess(data, opts);
642     CHECK_AND_PRINT_LOG(err == E_OK, "PostProcess failed! err %{public}d", err);
643 
644     if (!opts.path.empty()) {
645         fileName = GetThumbnailPathHighlight(data.path, thumbSuffix, data.timeStamp);
646     }
647     return E_OK;
648 }
649 
IsLocalThumbnailAvailable(ThumbnailData & data,ThumbnailType thumbType)650 bool IsLocalThumbnailAvailable(ThumbnailData &data, ThumbnailType thumbType)
651 {
652     string tmpPath = "";
653     switch (thumbType) {
654         case ThumbnailType::THUMB:
655         case ThumbnailType::THUMB_ASTC:
656             tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
657             break;
658         case ThumbnailType::LCD:
659             tmpPath =  GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
660             break;
661         default:
662             break;
663     }
664     return access(tmpPath.c_str(), F_OK) == 0;
665 }
666 
IsLocalKeyFrameThumbnailAvailable(ThumbnailData & data,int32_t type)667 bool IsLocalKeyFrameThumbnailAvailable(ThumbnailData &data, int32_t type)
668 {
669     string tmpPath = "";
670     switch (type) {
671         case KEY_FRAME_THM:
672         case KEY_FRAME_THM_ASTC:
673             tmpPath = GetLocalKeyFrameThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX, data.timeStamp);
674             break;
675         case KEY_FRAME_LCD:
676             tmpPath = GetLocalKeyFrameThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX, data.timeStamp);
677             break;
678         default:
679             break;
680     }
681     return access(tmpPath.c_str(), F_OK) == 0;
682 }
683 
CacheStreamReadThumbDbStatus(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType)684 void CacheStreamReadThumbDbStatus(ThumbRdbOpt& opts, ThumbnailData& data, ThumbnailType thumbType)
685 {
686     CHECK_AND_RETURN_LOG(opts.table == PhotoColumn::PHOTOS_TABLE, "Not photos table!");
687 
688     Size tmpSize;
689     CHECK_AND_RETURN_LOG(ThumbnailUtils::GetLocalThumbSize(data, thumbType, tmpSize),
690         "GetLocalThumbSize failed");
691 
692     ValuesBucket& values = data.rdbUpdateCache;
693     switch (thumbType) {
694         case ThumbnailType::LCD:
695             ThumbnailUtils::SetThumbnailSizeValue(values, tmpSize, PhotoColumn::PHOTO_LCD_SIZE);
696             values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(LcdReady::GENERATE_LCD_COMPLETED));
697             break;
698         case ThumbnailType::THUMB:
699         case ThumbnailType::THUMB_ASTC:
700             ThumbnailUtils::SetThumbnailSizeValue(values, tmpSize, PhotoColumn::PHOTO_THUMB_SIZE);
701             break;
702         default:
703             break;
704     }
705     if (thumbType == ThumbnailType::LCD && opts.table == PhotoColumn::PHOTOS_TABLE &&
706         !MediaLibraryBundleManager::GetInstance()->GetClientBundleName().empty()) {
707         values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, MediaFileUtils::UTCTimeMilliSeconds());
708     }
709 }
710 
UpdatePhotoLastVisitTimeAsync(ThumbnailData & data,ThumbRdbOpt & opts)711 void UpdatePhotoLastVisitTimeAsync(ThumbnailData &data, ThumbRdbOpt &opts)
712 {
713     auto updatePhotoLastVisitTime = [](std::shared_ptr<ThumbnailTaskData> &taskData) {
714         CHECK_AND_RETURN_LOG(taskData != nullptr, "UpdatePhotoLastVisitTimeAsync task data is nullptr!");
715         ThumbRdbOpt opts = taskData->opts_;
716         ThumbnailData data = taskData->thumbnailData_;
717         NativeRdb::ValuesBucket values;
718         values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, MediaFileUtils::UTCTimeMilliSeconds());
719         auto ret = ThumbnailRdbUtils::UpdateRdbStoreById(opts, data.id, values);
720         CHECK_AND_PRINT_LOG(ret == E_OK, "UpdateRdbStoreById err: %{public}d. id: %{public}s path: %{public}s",
721             ret, data.id.c_str(), DfxUtils::GetSafePath(data.path).c_str());
722     };
723     ThumbnailGenerateExecute executor = updatePhotoLastVisitTime;
724     IThumbnailHelper::AddThumbnailGenerateTask(executor, opts, data,
725         ThumbnailTaskType::ASYNC_UPDATE_RDB, ThumbnailTaskPriority::LOW);
726 }
727 
GetThumbnailPixelMap(ThumbnailData & data,ThumbRdbOpt & opts,ThumbnailType thumbType)728 int32_t ThumbnailGenerateHelper::GetThumbnailPixelMap(ThumbnailData& data, ThumbRdbOpt &opts, ThumbnailType thumbType)
729 {
730     int32_t err;
731     ThumbnailWait thumbnailWait(false);
732     thumbnailWait.CheckAndWait(opts.row, thumbType == ThumbnailType::LCD);
733     ThumbnailUtils::GetThumbnailInfo(opts, data);
734     ThumbnailUtils::QueryThumbnailDataFromFileId(opts, data.id, data, err);
735 
736     string fileName;
737     err = GetAvailableFile(opts, data, thumbType, fileName);
738     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "GetAvailableFile failed, path: %{public}s",
739         DfxUtils::GetSafePath(data.path).c_str());
740 
741     bool isLocalThumbnailAvailable = IsLocalThumbnailAvailable(data, thumbType);
742     DfxTimer dfxTimer(thumbType == ThumbnailType::LCD ? DfxType::CLOUD_LCD_OPEN : DfxType::CLOUD_DEFAULT_OPEN,
743         INVALID_DFX, thumbType == ThumbnailType::LCD ? CLOUD_LCD_TIME_OUT : CLOUD_DEFAULT_TIME_OUT, false);
744 
745     string absFilePath;
746     CHECK_AND_RETURN_RET_LOG(PathToRealPath(fileName, absFilePath), E_ERR,
747         "file is not real path, file path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
748     auto fd = open(absFilePath.c_str(), O_RDONLY);
749     dfxTimer.End();
750     if (fd < 0) {
751         DfxManager::GetInstance()->HandleThumbnailError(absFilePath,
752             thumbType == ThumbnailType::LCD ? DfxType::CLOUD_LCD_OPEN : DfxType::CLOUD_DEFAULT_OPEN, -errno);
753         return -errno;
754     }
755     if (data.isOpeningCloudFile && ThumbnailUtils::IsExCloudThumbnail(data)) {
756         IThumbnailHelper::DoRotateThumbnailEx(opts, data, fd, thumbType);
757         fileName = GetThumbnailPath(data.path,
758             thumbType == ThumbnailType::LCD ? THUMBNAIL_LCD_SUFFIX : THUMBNAIL_THUMB_SUFFIX);
759         CHECK_AND_RETURN_RET_LOG(PathToRealPath(fileName, absFilePath), E_ERR,
760             "file is not real path, file path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
761         fd = open(absFilePath.c_str(), O_RDONLY);
762         if (fd < 0) {
763             MEDIA_ERR_LOG("Rotate thumb failed, path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
764             DfxManager::GetInstance()->HandleThumbnailError(absFilePath,
765                 thumbType == ThumbnailType::LCD ? DfxType::CLOUD_LCD_OPEN : DfxType::CLOUD_DEFAULT_OPEN, -errno);
766             return -errno;
767         }
768     }
769     if (!isLocalThumbnailAvailable) {
770         CacheStreamReadThumbDbStatus(opts, data, thumbType);
771         return fd;
772     }
773     if (thumbType == ThumbnailType::LCD && opts.table == PhotoColumn::PHOTOS_TABLE &&
774         !MediaLibraryBundleManager::GetInstance()->GetClientBundleName().empty()) {
775         UpdatePhotoLastVisitTimeAsync(data, opts);
776     }
777     return fd;
778 }
779 
GetKeyFrameThumbnailPixelMap(ThumbRdbOpt & opts,int32_t & timeStamp,int32_t & type)780 int32_t ThumbnailGenerateHelper::GetKeyFrameThumbnailPixelMap(ThumbRdbOpt &opts, int32_t &timeStamp, int32_t &type)
781 {
782     ThumbnailWait thumbnailWait(false);
783     thumbnailWait.CheckAndWait(opts.row, type == KEY_FRAME_LCD);
784     vector<int> trackInfos;
785     int32_t errTracks = E_ERR;
786     if (!ThumbnailUtils::GetHighlightTracks(opts, trackInfos, errTracks)) {
787         MEDIA_ERR_LOG("Failed to GetHighlightTracks %{public}d", errTracks);
788         return errTracks;
789     }
790     if (find(trackInfos.begin(), trackInfos.end(), timeStamp) == trackInfos.end()) {
791         timeStamp = 0;
792         MEDIA_ERR_LOG("Not the frame of the highlight tracks, return the first frame");
793     }
794 
795     ThumbnailData thumbnailData;
796     thumbnailData.path = opts.path;
797     thumbnailData.id = opts.row;
798     thumbnailData.dateTaken = opts.dateTaken;
799     thumbnailData.fileUri = opts.fileUri;
800     thumbnailData.stats.uri = thumbnailData.fileUri;
801     thumbnailData.timeStamp = std::to_string(timeStamp);
802     thumbnailData.tracks = "tracks";
803 
804     string fileName;
805     int err = GetAvailableKeyFrameFile(opts, thumbnailData, type, fileName);
806     if (err != E_OK) {
807         MEDIA_ERR_LOG("GetAvailableKeyFrameFile failed, path: %{public}s",
808             DfxUtils::GetSafePath(thumbnailData.path).c_str());
809         return err;
810     }
811 
812     string absFilePath;
813     if (!PathToRealPath(fileName, absFilePath)) {
814         MEDIA_ERR_LOG("file is not real path, file path: %{public}s",
815             DfxUtils::GetSafePath(fileName).c_str());
816         return E_ERR;
817     }
818 
819     auto fd = open(absFilePath.c_str(), O_RDONLY);
820     if (fd < 0) {
821         MEDIA_ERR_LOG("GetKeyFrameThumbnailPixelMap: open file failed path: %{public}s, errno:%{public}d",
822             DfxUtils::GetSafePath(thumbnailData.path).c_str(), errno);
823         return E_ERR;
824     }
825     return fd;
826 }
827 
GenerateHighlightThumbnailBackground(ThumbRdbOpt & opts)828 int32_t ThumbnailGenerateHelper::GenerateHighlightThumbnailBackground(ThumbRdbOpt &opts)
829 {
830     if (opts.store == nullptr) {
831         MEDIA_ERR_LOG("rdbStore is not init");
832         return E_ERR;
833     }
834 
835     vector<ThumbnailData> infos;
836     int32_t err = GetNoHighlightData(opts, infos);
837     if (err != E_OK) {
838         MEDIA_ERR_LOG("Failed to GetNoHighlightData %{public}d", err);
839         return err;
840     }
841     if (infos.empty()) {
842         MEDIA_DEBUG_LOG("No need generate highlight thumbnail.");
843         return E_OK;
844     }
845 
846     for (uint32_t i = 0; i < infos.size(); i++) {
847         opts.row = infos[i].id;
848         infos[i].loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
849         IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
850             opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
851     }
852     return E_OK;
853 }
854 
TriggerHighlightThumbnail(ThumbRdbOpt & opts,std::string & id,std::string & tracks,std::string & trigger,std::string & genType)855 int32_t ThumbnailGenerateHelper::TriggerHighlightThumbnail(ThumbRdbOpt &opts, std::string &id, std::string &tracks,
856     std::string &trigger, std::string &genType)
857 {
858     ThumbnailData data;
859     data.id = id;
860     data.tracks = tracks;
861     data.trigger = trigger;
862 
863     int32_t err = E_ERR;
864     if (!ThumbnailUtils::QueryHighlightTriggerPath(opts, data, err)) {
865         MEDIA_ERR_LOG("Failed to QueryHighlightTriggerPath %{public}d", err);
866         return err;
867     }
868     if (genType == MEDIA_DATA_DB_UPDATE_TYPE && ThumbnailFileUtils::DeleteBeginTimestampDir(data)) {
869         MEDIA_INFO_LOG("Delete beginTimeStampDir success");
870     }
871     opts.row = data.id;
872     data.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
873     IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
874         opts, data, ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
875     return E_OK;
876 }
877 
UpgradeThumbnailBackgroundTask(std::shared_ptr<ThumbnailTaskData> & data)878 void UpgradeThumbnailBackgroundTask(std::shared_ptr<ThumbnailTaskData> &data)
879 {
880     CHECK_AND_RETURN_LOG(data != nullptr, "Data is null");
881     auto &thumbnailData = data->thumbnailData_;
882     CHECK_AND_RETURN_INFO_LOG(thumbnailData.isLocalFile || ThumbnailFileUtils::IsWifiConnected(),
883         "Wifi is not connected, cloud thumbnail can not be generated, id:%{public}s, path:%{public}s",
884         thumbnailData.id.c_str(), DfxUtils::GetSafePath(thumbnailData.path).c_str());
885     IThumbnailHelper::CreateLcdAndThumbnail(data);
886 }
887 
UpgradeThumbnailBackground(ThumbRdbOpt & opts,bool isWifiConnected)888 int32_t ThumbnailGenerateHelper::UpgradeThumbnailBackground(ThumbRdbOpt &opts, bool isWifiConnected)
889 {
890     if (opts.store == nullptr) {
891         MEDIA_ERR_LOG("rdbStore is not init");
892         return E_ERR;
893     }
894     CHECK_AND_RETURN_RET_LOG(ThumbnailFileUtils::CheckRemainSpaceMeetCondition(THUMBNAIL_FREE_SIZE_LIMIT_10),
895         E_FREE_SIZE_NOT_ENOUGH, "Free size is not enough");
896 
897     vector<ThumbnailData> infos;
898     int32_t err = GetThumbnailDataNeedUpgrade(opts, infos, isWifiConnected);
899     if (err != E_OK) {
900         MEDIA_ERR_LOG("Failed to GetThumbnailDataNeedUpgrade %{public}d", err);
901         return err;
902     }
903     if (infos.empty()) {
904         MEDIA_DEBUG_LOG("No need upgrade thumbnail.");
905         return E_OK;
906     }
907     MEDIA_INFO_LOG("Will upgrade %{public}zu photo thumbnails, wifi: %{public}d.", infos.size(), isWifiConnected);
908     for (uint32_t i = 0; i < infos.size(); i++) {
909         opts.row = infos[i].id;
910         ThumbnailUtils::RecordStartGenerateStats(infos[i].stats, GenerateScene::UPGRADE, LoadSourceType::LOCAL_PHOTO);
911         infos[i].loaderOpts.loadingStates = SourceLoader::UPGRADE_SOURCE_LOADING_STATES;
912         CHECK_AND_EXECUTE(infos[i].isLocalFile, ThumbnailUtils::HandleImageExifRotate(infos[i]));
913         IThumbnailHelper::AddThumbnailGenerateTask(UpgradeThumbnailBackgroundTask,
914             opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
915     }
916     return E_OK;
917 }
918 
RestoreAstcDualFrame(ThumbRdbOpt & opts,const int32_t & restoreAstcCount)919 int32_t ThumbnailGenerateHelper::RestoreAstcDualFrame(ThumbRdbOpt &opts, const int32_t &restoreAstcCount)
920 {
921     CHECK_AND_RETURN_RET_LOG(restoreAstcCount > 0, E_ERR, "RestoreAstcCount:%{public}d is invalid", restoreAstcCount);
922     CHECK_AND_RETURN_RET_LOG(opts.store != nullptr, E_ERR, "RdbStore is not init");
923     vector<ThumbnailData> infos;
924     int32_t err = 0;
925     if (!ThumbnailUtils::QueryNoAstcInfosRestored(opts, infos, err, restoreAstcCount)) {
926         MEDIA_ERR_LOG("Failed to QueryNoAstcInfosRestored %{public}d", err);
927         return err;
928     }
929     if (infos.empty()) {
930         MEDIA_INFO_LOG("No photos need resotre astc.");
931         return E_OK;
932     }
933 
934     MEDIA_INFO_LOG("create astc for restored dual frame photos count:%{public}zu, restoreAstcCount:%{public}d",
935         infos.size(), restoreAstcCount);
936 
937     for (auto &info : infos) {
938         opts.row = info.id;
939         info.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
940         ThumbnailUtils::RecordStartGenerateStats(info.stats, GenerateScene::RESTORE, LoadSourceType::LOCAL_PHOTO);
941         IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateThumbnail, opts, info,
942             ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::MID);
943     }
944 
945     MEDIA_INFO_LOG("create astc for restored dual frame photos finished");
946     return E_OK;
947 }
948 
GetThumbnailDataNeedUpgrade(ThumbRdbOpt & opts,std::vector<ThumbnailData> & outDatas,bool isWifiConnected)949 int32_t ThumbnailGenerateHelper::GetThumbnailDataNeedUpgrade(ThumbRdbOpt &opts, std::vector<ThumbnailData> &outDatas,
950     bool isWifiConnected)
951 {
952     int32_t err = E_ERR;
953     if (!ThumbnailUtils::QueryUpgradeThumbnailInfos(opts, outDatas, isWifiConnected, err)) {
954         MEDIA_ERR_LOG("Failed to QueryUpgradeThumbnailInfos %{public}d", err);
955         return err;
956     }
957     return E_OK;
958 }
959 
CheckMonthAndYearKvStoreValid(ThumbRdbOpt & opts)960 void ThumbnailGenerateHelper::CheckMonthAndYearKvStoreValid(ThumbRdbOpt &opts)
961 {
962     bool isMonthKvStoreValid = MediaLibraryKvStoreManager::GetInstance().IsKvStoreValid(KvStoreValueType::MONTH_ASTC);
963     bool isYearKvStoreValid = MediaLibraryKvStoreManager::GetInstance().IsKvStoreValid(KvStoreValueType::YEAR_ASTC);
964     if (isMonthKvStoreValid && isYearKvStoreValid) {
965         return;
966     }
967     CHECK_AND_RETURN_LOG(opts.store != nullptr, "rdbStore is not init");
968 
969     MEDIA_INFO_LOG("KvStore is invalid, start update rdb");
970     if (opts.store->ExecuteSql(SQL_REFRESH_THUMBNAIL_READY) != NativeRdb::E_OK) {
971         MEDIA_ERR_LOG("Update rdb failed");
972         return;
973     }
974     MEDIA_INFO_LOG("Update rdb successfully");
975 
976     if (!isMonthKvStoreValid) {
977         MediaLibraryKvStoreManager::GetInstance().RebuildInvalidKvStore(KvStoreValueType::MONTH_ASTC);
978     }
979 
980     if (!isYearKvStoreValid) {
981         MediaLibraryKvStoreManager::GetInstance().RebuildInvalidKvStore(KvStoreValueType::YEAR_ASTC);
982     }
983 
984     Acl::AclSetDatabase();
985     MEDIA_INFO_LOG("RebuildInvalidKvStore finish, isMonthKvStoreValid: %{public}d, isYearKvStoreValid: %{public}d",
986         isMonthKvStoreValid, isYearKvStoreValid);
987 }
988 
RepairExifRotateBackgroundTask(std::shared_ptr<ThumbnailTaskData> & data)989 void RepairExifRotateBackgroundTask(std::shared_ptr<ThumbnailTaskData> &data)
990 {
991     CHECK_AND_RETURN_LOG(data != nullptr, "Data is null");
992     auto &opts = data->opts_;
993     auto &thumbnailData = data->thumbnailData_;
994     int err;
995     ThumbnailUtils::QueryThumbnailDataFromFileId(data->opts_, thumbnailData.id, thumbnailData, err);
996     CHECK_AND_RETURN_LOG(err == E_OK, "Query data from fileId failed, id: %{public}s", thumbnailData.id.c_str());
997     CHECK_AND_RETURN_WARN_LOG(thumbnailData.exifRotate == 0 && thumbnailData.isLocalFile,
998         "ExifRotate is not zero or photo is not local, id:%{public}s, position:%{public}d, exifRotate:%{public}d",
999         thumbnailData.id.c_str(), thumbnailData.position, thumbnailData.exifRotate);
1000 
1001     DirtyType dirtyType = DirtyType::TYPE_MDIRTY;
1002     thumbnailData.exifRotate = static_cast<int32_t>(ExifRotateType::TOP_LEFT);
1003     thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
1004     ThumbnailUtils::RecordStartGenerateStats(thumbnailData.stats, GenerateScene::REPAIR,
1005         LoadSourceType::LOCAL_PHOTO);
1006     if (thumbnailData.mediaType == MediaType::MEDIA_TYPE_IMAGE) {
1007         MediaImageFrameWorkUtils::GetExifRotate(thumbnailData.path, thumbnailData.exifRotate);
1008         if (thumbnailData.exifRotate != static_cast<int32_t>(ExifRotateType::TOP_LEFT)) {
1009             ThumbnailUtils::DeleteThumbnailDirAndAstc(opts, thumbnailData);
1010             IThumbnailHelper::CreateLcdAndThumbnail(data);
1011         }
1012     } else {
1013         MediaPlayerFrameWorkUtils::GetExifRotate(thumbnailData.path, thumbnailData.exifRotate);
1014         if (ExifRotateUtils::IsExifRotateWithFlip(thumbnailData.exifRotate)) {
1015             ThumbnailUtils::DeleteThumbnailDirAndAstc(opts, thumbnailData);
1016             IThumbnailHelper::CreateLcdAndThumbnail(data);
1017             dirtyType = DirtyType::TYPE_FDIRTY;
1018         }
1019     }
1020     CHECK_AND_EXECUTE(!thumbnailData.needUpdateDb,
1021         ThumbnailRdbUtils::UpdateExifRotateAndDirty(thumbnailData, dirtyType));
1022     MEDIA_INFO_LOG("Repair photo exif rotate, id:%{public}s, path:%{public}s, exifRotate:%{public}d",
1023         thumbnailData.id.c_str(), DfxUtils::GetSafePath(thumbnailData.path).c_str(), thumbnailData.exifRotate);
1024 }
1025 
RepairExifRotateBackground(ThumbRdbOpt & opts)1026 int32_t ThumbnailGenerateHelper::RepairExifRotateBackground(ThumbRdbOpt &opts)
1027 {
1028     CHECK_AND_RETURN_RET_LOG(opts.store != nullptr, E_ERR, "RdbStore is nullptr");
1029 
1030     vector<ThumbnailData> infos;
1031     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryLocalNoExifRotateInfos(opts, infos),
1032         E_ERR, "Failed to QueryNoExifRotateInfos");
1033     CHECK_AND_RETURN_RET_INFO_LOG(!infos.empty(), E_OK, "No need repair exif rotate");
1034 
1035     MEDIA_INFO_LOG("Will repair %{public}zu no exif photos", infos.size());
1036     for (uint32_t i = 0; i < infos.size(); i++) {
1037         opts.row = infos[i].id;
1038         IThumbnailHelper::AddThumbnailGenerateTask(RepairExifRotateBackgroundTask,
1039             opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
1040     }
1041     return E_OK;
1042 }
1043 
FixThumbnailExifRotateAfterDownloadAssetTask(std::shared_ptr<ThumbnailTaskData> & data)1044 void FixThumbnailExifRotateAfterDownloadAssetTask(std::shared_ptr<ThumbnailTaskData> &data)
1045 {
1046     CHECK_AND_RETURN_LOG(data != nullptr, "Data is null");
1047     auto &opts = data->opts_;
1048     auto &thumbnailData = data->thumbnailData_;
1049     int err;
1050     ThumbnailUtils::QueryThumbnailDataFromFileId(data->opts_, thumbnailData.id, thumbnailData, err);
1051     CHECK_AND_RETURN_LOG(err == E_OK, "Query data from fileId failed, id: %{public}s", thumbnailData.id.c_str());
1052 
1053     thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
1054     ThumbnailUtils::RecordStartGenerateStats(thumbnailData.stats, GenerateScene::REPAIR,
1055         LoadSourceType::LOCAL_PHOTO);
1056     IThumbnailHelper::CreateLcdAndThumbnail(data);
1057 }
1058 
FixThumbnailExifRotateAfterDownloadAsset(ThumbRdbOpt & opts)1059 int32_t ThumbnailGenerateHelper::FixThumbnailExifRotateAfterDownloadAsset(ThumbRdbOpt &opts)
1060 {
1061     ThumbnailData data;
1062     data.id = opts.fileId;
1063     opts.row = data.id;
1064     data.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
1065     IThumbnailHelper::AddThumbnailGenerateTask(FixThumbnailExifRotateAfterDownloadAssetTask,
1066         opts, data, ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::MID);
1067     return E_OK;
1068 }
1069 } // namespace Media
1070 } // namespace OHOS