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