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 "dfx_const.h"
23 #include "dfx_manager.h"
24 #include "dfx_timer.h"
25 #include "dfx_utils.h"
26 #include "ffrt.h"
27 #include "ffrt_inner.h"
28 #include "directory_ex.h"
29 #include "ithumbnail_helper.h"
30 #include "medialibrary_errno.h"
31 #include "medialibrary_kvstore_manager.h"
32 #include "medialibrary_photo_operations.h"
33 #include "medialibrary_type_const.h"
34 #include "media_file_utils.h"
35 #include "media_log.h"
36 #include "thumbnail_const.h"
37 #include "thumbnail_generate_worker_manager.h"
38 #include "thumbnail_source_loading.h"
39 #include "thumbnail_utils.h"
40
41 using namespace std;
42 using namespace OHOS::DistributedKv;
43 using namespace OHOS::NativeRdb;
44
45 namespace OHOS {
46 namespace Media {
47 const int FFRT_MAX_RESTORE_ASTC_THREADS = 4;
48 const std::string SQL_REFRESH_THUMBNAIL_READY =
49 " Update " + PhotoColumn::PHOTOS_TABLE + " SET " + PhotoColumn::PHOTO_THUMBNAIL_READY + " = 7 " +
50 " WHERE " + PhotoColumn::PHOTO_THUMBNAIL_READY + " != 0; END;";
51
CreateThumbnailFileScaned(ThumbRdbOpt & opts,bool isSync)52 int32_t ThumbnailGenerateHelper::CreateThumbnailFileScaned(ThumbRdbOpt &opts, bool isSync)
53 {
54 ThumbnailData thumbnailData;
55 ThumbnailUtils::GetThumbnailInfo(opts, thumbnailData);
56 thumbnailData.needResizeLcd = true;
57 thumbnailData.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
58 ThumbnailUtils::RecordStartGenerateStats(thumbnailData.stats, GenerateScene::LOCAL, LoadSourceType::LOCAL_PHOTO);
59 if (ThumbnailUtils::DeleteThumbExDir(thumbnailData)) {
60 MEDIA_ERR_LOG("Delete THM_EX directory, path: %{public}s, id: %{public}s",
61 DfxUtils::GetSafePath(thumbnailData.path).c_str(), thumbnailData.id.c_str());
62 }
63
64 if (isSync) {
65 WaitStatus status;
66 bool isSuccess = IThumbnailHelper::DoCreateLcdAndThumbnail(opts, thumbnailData, status);
67 if (status == WaitStatus::INSERT) {
68 IThumbnailHelper::UpdateThumbnailState(opts, thumbnailData, isSuccess);
69 }
70 ThumbnailUtils::RecordCostTimeAndReport(thumbnailData.stats);
71 } else {
72 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
73 opts, thumbnailData, ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::HIGH);
74 }
75 return E_OK;
76 }
77
CreateThumbnailBackground(ThumbRdbOpt & opts)78 int32_t ThumbnailGenerateHelper::CreateThumbnailBackground(ThumbRdbOpt &opts)
79 {
80 if (opts.store == nullptr) {
81 MEDIA_ERR_LOG("rdbStore is not init");
82 return E_ERR;
83 }
84
85 vector<ThumbnailData> infos;
86 int32_t err = GetNoThumbnailData(opts, infos);
87 if (err != E_OK) {
88 MEDIA_ERR_LOG("Failed to GetNoLThumbnailData %{private}d", err);
89 return err;
90 }
91
92 if (infos.empty()) {
93 MEDIA_DEBUG_LOG("No need generate thumbnail.");
94 return E_OK;
95 }
96
97 for (uint32_t i = 0; i < infos.size(); i++) {
98 opts.row = infos[i].id;
99 infos[i].loaderOpts.loadingStates = infos[i].isLocalFile ? SourceLoader::LOCAL_SOURCE_LOADING_STATES :
100 SourceLoader::CLOUD_SOURCE_LOADING_STATES;
101 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateThumbnail,
102 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
103 }
104
105 return E_OK;
106 }
107
CreateAstcBackground(ThumbRdbOpt & opts)108 int32_t ThumbnailGenerateHelper::CreateAstcBackground(ThumbRdbOpt &opts)
109 {
110 if (opts.store == nullptr) {
111 MEDIA_ERR_LOG("rdbStore is not init");
112 return E_ERR;
113 }
114
115 CheckMonthAndYearKvStoreValid(opts);
116 vector<ThumbnailData> infos;
117 int32_t err = GetNoAstcData(opts, infos);
118 if (err != E_OK) {
119 MEDIA_ERR_LOG("Failed to GetNoAstcData %{private}d", err);
120 return err;
121 }
122
123 auto kvStore = MediaLibraryKvStoreManager::GetInstance()
124 .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
125 if (infos.empty() || kvStore == nullptr) {
126 MEDIA_DEBUG_LOG("No need create Astc.");
127 return E_OK;
128 }
129
130 MEDIA_INFO_LOG("no astc data size: %{public}d", static_cast<int>(infos.size()));
131 for (uint32_t i = 0; i < infos.size(); i++) {
132 opts.row = infos[i].id;
133 ThumbnailUtils::RecordStartGenerateStats(infos[i].stats, GenerateScene::BACKGROUND,
134 LoadSourceType::LOCAL_PHOTO);
135 infos[i].loaderOpts.loadingStates = infos[i].isLocalFile ? SourceLoader::LOCAL_SOURCE_LOADING_STATES :
136 SourceLoader::CLOUD_SOURCE_LOADING_STATES;
137 if (infos[i].orientation != 0) {
138 infos[i].loaderOpts.loadingStates = infos[i].isLocalFile ? SourceLoader::LOCAL_SOURCE_LOADING_STATES :
139 SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES;
140 IThumbnailHelper::AddThumbnailGenerateTask(infos[i].isLocalFile ?
141 IThumbnailHelper::CreateThumbnail : IThumbnailHelper::CreateAstcEx, opts, infos[i],
142 ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
143 } else {
144 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateAstc,
145 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
146 }
147 }
148 return E_OK;
149 }
150
CreateAstcCloudDownload(ThumbRdbOpt & opts,bool isCloudInsertTaskPriorityHigh)151 int32_t ThumbnailGenerateHelper::CreateAstcCloudDownload(ThumbRdbOpt &opts, bool isCloudInsertTaskPriorityHigh)
152 {
153 ThumbnailData data;
154 ThumbnailUtils::RecordStartGenerateStats(data.stats, GenerateScene::CLOUD, LoadSourceType::LOCAL_PHOTO);
155 int err = 0;
156 ThumbnailUtils::QueryThumbnailDataFromFileId(opts, opts.fileId, data, err);
157 if (err != E_OK) {
158 MEDIA_ERR_LOG("QueryThumbnailDataFromFileId failed, path: %{public}s",
159 DfxUtils::GetSafePath(data.path).c_str());
160 return err;
161 }
162 ValuesBucket values;
163 Size lcdSize;
164 if (data.mediaType == MEDIA_TYPE_VIDEO && ThumbnailUtils::GetLocalThumbSize(data, ThumbnailType::LCD, lcdSize)) {
165 ThumbnailUtils::SetThumbnailSizeValue(values, lcdSize, PhotoColumn::PHOTO_LCD_SIZE);
166 int changedRows;
167 int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
168 vector<string> { data.id });
169 if (err != NativeRdb::E_OK) {
170 MEDIA_ERR_LOG("RdbStore lcd size failed! %{public}d", err);
171 }
172 }
173 ThumbnailTaskPriority priority = isCloudInsertTaskPriorityHigh ?
174 ThumbnailTaskPriority::MID : ThumbnailTaskPriority::LOW;
175 ThumbnailTaskType taskType = isCloudInsertTaskPriorityHigh ?
176 ThumbnailTaskType::FOREGROUND : ThumbnailTaskType::BACKGROUND;
177
178 data.loaderOpts.loadingStates = SourceLoader::CLOUD_SOURCE_LOADING_STATES;
179 if (data.orientation != 0) {
180 data.loaderOpts.loadingStates = SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES;
181 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateAstcEx, opts, data, taskType, priority);
182 return E_OK;
183 }
184 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateAstc, opts, data, taskType, priority);
185 return E_OK;
186 }
187
CreateAstcBatchOnDemand(ThumbRdbOpt & opts,NativeRdb::RdbPredicates & predicate,int32_t requestId)188 int32_t ThumbnailGenerateHelper::CreateAstcBatchOnDemand(
189 ThumbRdbOpt &opts, NativeRdb::RdbPredicates &predicate, int32_t requestId)
190 {
191 if (opts.store == nullptr) {
192 MEDIA_ERR_LOG("rdbStore is not init");
193 return E_ERR;
194 }
195
196 vector<ThumbnailData> infos;
197 int32_t err = 0;
198 if (!ThumbnailUtils::QueryNoAstcInfosOnDemand(opts, infos, predicate, err)) {
199 MEDIA_ERR_LOG("Failed to QueryNoAstcInfos %{public}d", err);
200 return err;
201 }
202 if (infos.empty()) {
203 MEDIA_DEBUG_LOG("No need create Astc.");
204 return E_THUMBNAIL_ASTC_ALL_EXIST;
205 }
206
207 MEDIA_INFO_LOG("no astc data size: %{public}d, requestId: %{public}d", static_cast<int>(infos.size()), requestId);
208 for (auto& info : infos) {
209 opts.row = info.id;
210 ThumbnailUtils::RecordStartGenerateStats(info.stats, GenerateScene::FOREGROUND, LoadSourceType::LOCAL_PHOTO);
211 if (info.isLocalFile) {
212 info.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
213 IThumbnailHelper::AddThumbnailGenBatchTask(IThumbnailHelper::CreateThumbnail, opts, info, requestId);
214 continue;
215 }
216 if (info.orientation != 0) {
217 info.loaderOpts.loadingStates = SourceLoader::CLOUD_LCD_SOURCE_LOADING_STATES;
218 } else if (info.mediaType == MEDIA_TYPE_VIDEO) {
219 info.loaderOpts.loadingStates = SourceLoader::ALL_SOURCE_LOADING_CLOUD_VIDEO_STATES;
220 } else {
221 info.loaderOpts.loadingStates = SourceLoader::ALL_SOURCE_LOADING_STATES;
222 }
223 IThumbnailHelper::AddThumbnailGenBatchTask(info.orientation == 0 ?
224 IThumbnailHelper::CreateAstc : IThumbnailHelper::CreateAstcEx, opts, info, requestId);
225 }
226 return E_OK;
227 }
228
NeedGenerateLocalLcd(ThumbnailData & data)229 bool NeedGenerateLocalLcd(ThumbnailData &data)
230 {
231 std::string lcdLocalPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
232 size_t lcdSize = -1;
233
234 // Local LCD exist, and its size is less than upload limit
235 if (access(lcdLocalPath.c_str(), F_OK) == 0 && MediaFileUtils::GetFileSize(lcdLocalPath, lcdSize) &&
236 lcdSize < LCD_UPLOAD_LIMIT_SIZE) {
237 return false;
238 }
239 MEDIA_INFO_LOG("Local file Lcd need to be generate, size: %{public}d, path: %{public}s",
240 static_cast<int>(lcdSize), DfxUtils::GetSafePath(data.path).c_str());
241 return true;
242 }
243
CreateLcdBackground(ThumbRdbOpt & opts)244 int32_t ThumbnailGenerateHelper::CreateLcdBackground(ThumbRdbOpt &opts)
245 {
246 if (opts.store == nullptr) {
247 return E_ERR;
248 }
249
250 vector<ThumbnailData> infos;
251 int32_t err = GetNoLcdData(opts, infos);
252 if (err != E_OK) {
253 MEDIA_ERR_LOG("Failed to GetNoLcdData %{private}d", err);
254 return err;
255 }
256 if (infos.empty()) {
257 MEDIA_DEBUG_LOG("No need create Lcd.");
258 return E_THUMBNAIL_LCD_ALL_EXIST;
259 }
260
261 MEDIA_INFO_LOG("No lcd data size: %{public}d", static_cast<int>(infos.size()));
262 for (uint32_t i = 0; i < infos.size(); i++) {
263 opts.row = infos[i].id;
264
265 // Check whether LCD exists or is over upload limit, if it does, just update the database
266 if (!NeedGenerateLocalLcd(infos[i])) {
267 MEDIA_INFO_LOG("Skip CreateLcdBackground, lcd exists: %{public}s",
268 DfxUtils::GetSafePath(infos[i].path).c_str());
269 ThumbnailUtils::UpdateLcdReadyStatus(opts, infos[i], err, LcdReady::GENERATE_LCD_COMPLETED);
270 continue;
271 }
272 infos[i].loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
273 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcd,
274 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
275 }
276 return E_OK;
277 }
278
CheckLcdSizeAndUpdateStatus(ThumbRdbOpt & opts)279 int32_t ThumbnailGenerateHelper::CheckLcdSizeAndUpdateStatus(ThumbRdbOpt &opts)
280 {
281 if (opts.store == nullptr) {
282 return E_ERR;
283 }
284
285 vector<ThumbnailData> infos;
286 int32_t err = GetLocalNoLcdData(opts, infos);
287 if (err != E_OK) {
288 MEDIA_ERR_LOG("Failed to CheckLcdSizeAndUpdateStatus %{public}d", err);
289 return err;
290 }
291 if (infos.empty()) {
292 MEDIA_INFO_LOG("No need CheckLcdSizeAndUpdateStatus.");
293 return E_THUMBNAIL_LCD_ALL_EXIST;
294 }
295
296 MEDIA_INFO_LOG("CheckLcdSizeAndUpdateStatus size: %{public}d", static_cast<int>(infos.size()));
297 for (uint32_t i = 0; i < infos.size(); i++) {
298 opts.row = infos[i].id;
299
300 // Check whether LCD exists or is over upload limit, if it does, just update the database
301 if (!NeedGenerateLocalLcd(infos[i])) {
302 MEDIA_INFO_LOG("Check lcd size succeeded, lcd exists: %{public}s",
303 DfxUtils::GetSafePath(infos[i].path).c_str());
304 ThumbnailUtils::UpdateLcdReadyStatus(opts, infos[i], err, LcdReady::GENERATE_LCD_COMPLETED);
305 }
306 }
307 return E_OK;
308 }
309
GetLcdCount(ThumbRdbOpt & opts,int & outLcdCount)310 int32_t ThumbnailGenerateHelper::GetLcdCount(ThumbRdbOpt &opts, int &outLcdCount)
311 {
312 int32_t err = E_ERR;
313 if (!ThumbnailUtils::QueryLcdCount(opts, outLcdCount, err)) {
314 MEDIA_ERR_LOG("Failed to QueryLcdCount %{private}d", err);
315 return err;
316 }
317 return E_OK;
318 }
319
GetNoLcdData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)320 int32_t ThumbnailGenerateHelper::GetNoLcdData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
321 {
322 int32_t err = E_ERR;
323 if (!ThumbnailUtils::QueryNoLcdInfos(opts, outDatas, err)) {
324 MEDIA_ERR_LOG("Failed to QueryNoLcdInfos %{private}d", err);
325 return err;
326 }
327 return E_OK;
328 }
329
GetLocalNoLcdData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)330 int32_t ThumbnailGenerateHelper::GetLocalNoLcdData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
331 {
332 int32_t err = E_ERR;
333 if (!ThumbnailUtils::QueryLocalNoLcdInfos(opts, outDatas, err)) {
334 MEDIA_ERR_LOG("Failed to QueryLocalNoLcdInfos %{private}d", err);
335 return err;
336 }
337 return E_OK;
338 }
339
GetNoThumbnailData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)340 int32_t ThumbnailGenerateHelper::GetNoThumbnailData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
341 {
342 int32_t err = E_ERR;
343 if (!ThumbnailUtils::QueryNoThumbnailInfos(opts, outDatas, err)) {
344 MEDIA_ERR_LOG("Failed to QueryNoThumbnailInfos %{private}d", err);
345 return err;
346 }
347 return E_OK;
348 }
349
GetNoAstcData(ThumbRdbOpt & opts,vector<ThumbnailData> & outDatas)350 int32_t ThumbnailGenerateHelper::GetNoAstcData(ThumbRdbOpt &opts, vector<ThumbnailData> &outDatas)
351 {
352 int32_t err = E_ERR;
353 if (!ThumbnailUtils::QueryNoAstcInfos(opts, outDatas, err)) {
354 MEDIA_ERR_LOG("Failed to QueryNoAstcInfos %{public}d", err);
355 return err;
356 }
357 return E_OK;
358 }
359
GetNewThumbnailCount(ThumbRdbOpt & opts,const int64_t & time,int & count)360 int32_t ThumbnailGenerateHelper::GetNewThumbnailCount(ThumbRdbOpt &opts, const int64_t &time, int &count)
361 {
362 int32_t err = E_ERR;
363 if (!ThumbnailUtils::QueryNewThumbnailCount(opts, time, count, err)) {
364 MEDIA_ERR_LOG("Failed to QueryNoThumbnailInfos %{private}d", err);
365 return err;
366 }
367 return E_OK;
368 }
369
GenerateLocalThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType)370 bool GenerateLocalThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, ThumbnailType thumbType)
371 {
372 data.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
373 WaitStatus status;
374 if (thumbType == ThumbnailType::LCD && !IThumbnailHelper::DoCreateLcd(opts, data, status)) {
375 MEDIA_ERR_LOG("Get lcd thumbnail pixelmap, doCreateLcd failed: %{public}s",
376 DfxUtils::GetSafePath(data.path).c_str());
377 return false;
378 }
379 if (thumbType != ThumbnailType::LCD) {
380 bool isSuccess = IThumbnailHelper::DoCreateThumbnail(opts, data, status);
381 if (status == WaitStatus::INSERT) {
382 IThumbnailHelper::UpdateThumbnailState(opts, data, isSuccess);
383 }
384 if (!isSuccess) {
385 MEDIA_ERR_LOG("Get default thumbnail pixelmap, doCreateThumbnail failed: %{public}s",
386 DfxUtils::GetSafePath(data.path).c_str());
387 return false;
388 }
389 }
390 return true;
391 }
392
GetAvailableFile(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType,std::string & fileName)393 int32_t ThumbnailGenerateHelper::GetAvailableFile(ThumbRdbOpt &opts, ThumbnailData &data, ThumbnailType thumbType,
394 std::string &fileName)
395 {
396 string thumbSuffix = GetThumbSuffix(thumbType);
397 fileName = GetThumbnailPath(data.path, thumbSuffix);
398 if (thumbType == ThumbnailType::THUMB_ASTC) {
399 // Try to get jpeg thumbnail instead if there is no astc file
400 if (access(fileName.c_str(), F_OK) == 0) {
401 return E_OK;
402 } else {
403 fileName = GetThumbnailPath(data.path, GetThumbSuffix(ThumbnailType::THUMB));
404 }
405 }
406
407 // No need to create thumbnails if corresponding file exists
408 if (access(fileName.c_str(), F_OK) == 0) {
409 MEDIA_INFO_LOG("File exists, path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
410 return E_OK;
411 }
412
413 // Check if unrotated file exists
414 string fileParentPath = MediaFileUtils::GetParentPath(fileName);
415 string tempFileName = fileParentPath + "/THM_EX" + fileName.substr(fileParentPath.length());
416 if (access(tempFileName.c_str(), F_OK) == 0) {
417 fileName = tempFileName;
418 data.isOpeningCloudFile = true;
419 MEDIA_INFO_LOG("Unrotated file exists, path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
420 return E_OK;
421 }
422
423 MEDIA_INFO_LOG("No available file, create thumbnail, path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
424 if (!GenerateLocalThumbnail(opts, data, thumbType)) {
425 MEDIA_ERR_LOG("GenerateLocalThumbnail failed, path: %{public}s", DfxUtils::GetSafePath(tempFileName).c_str());
426 return E_THUMBNAIL_LOCAL_CREATE_FAIL;
427 }
428 if (!opts.path.empty()) {
429 fileName = GetThumbnailPath(data.path, thumbSuffix);
430 }
431 return E_OK;
432 }
433
IsLocalThumbnailAvailable(ThumbnailData & data,ThumbnailType thumbType)434 bool IsLocalThumbnailAvailable(ThumbnailData &data, ThumbnailType thumbType)
435 {
436 string tmpPath = "";
437 switch (thumbType) {
438 case ThumbnailType::THUMB:
439 case ThumbnailType::THUMB_ASTC:
440 tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
441 break;
442 case ThumbnailType::LCD:
443 tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
444 break;
445 default:
446 break;
447 }
448 return access(tmpPath.c_str(), F_OK) == 0;
449 }
450
UpdateStreamReadThumbDbStatus(ThumbRdbOpt & opts,ThumbnailData & data,ThumbnailType thumbType)451 void UpdateStreamReadThumbDbStatus(ThumbRdbOpt& opts, ThumbnailData& data, ThumbnailType thumbType)
452 {
453 ValuesBucket values;
454 Size tmpSize;
455 if (!ThumbnailUtils::GetLocalThumbSize(data, thumbType, tmpSize)) {
456 return;
457 }
458 switch (thumbType) {
459 case ThumbnailType::LCD:
460 ThumbnailUtils::SetThumbnailSizeValue(values, tmpSize, PhotoColumn::PHOTO_LCD_SIZE);
461 values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(LcdReady::GENERATE_LCD_COMPLETED));
462 break;
463 case ThumbnailType::THUMB:
464 case ThumbnailType::THUMB_ASTC:
465 ThumbnailUtils::SetThumbnailSizeValue(values, tmpSize, PhotoColumn::PHOTO_THUMB_SIZE);
466 break;
467 default:
468 break;
469 }
470 int changedRows = 0;
471 int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
472 vector<string> { data.id });
473 if (err != NativeRdb::E_OK) {
474 MEDIA_ERR_LOG("UpdateStreamReadThumbDbStatus failed! %{public}d", err);
475 }
476 }
477
UpdateThumbStatus(ThumbRdbOpt & opts,ThumbnailType thumbType,ThumbnailData & thumbnailData,int & err,bool & isLocalThumbnailAvailable)478 void UpdateThumbStatus(ThumbRdbOpt &opts, ThumbnailType thumbType, ThumbnailData& thumbnailData, int& err,
479 bool& isLocalThumbnailAvailable)
480 {
481 if (!isLocalThumbnailAvailable) {
482 UpdateStreamReadThumbDbStatus(opts, thumbnailData, thumbType);
483 }
484 if (thumbType == ThumbnailType::LCD && opts.table == PhotoColumn::PHOTOS_TABLE) {
485 ThumbnailUtils::UpdateVisitTime(opts, thumbnailData, err);
486 }
487 }
488
GetThumbnailPixelMap(ThumbRdbOpt & opts,ThumbnailType thumbType)489 int32_t ThumbnailGenerateHelper::GetThumbnailPixelMap(ThumbRdbOpt &opts, ThumbnailType thumbType)
490 {
491 ThumbnailWait thumbnailWait(false);
492 thumbnailWait.CheckAndWait(opts.row, thumbType == ThumbnailType::LCD);
493 ThumbnailData thumbnailData;
494 ThumbnailUtils::GetThumbnailInfo(opts, thumbnailData);
495
496 int err;
497 ThumbnailUtils::QueryThumbnailDataFromFileId(opts, thumbnailData.id, thumbnailData, err);
498
499 string fileName;
500 err = GetAvailableFile(opts, thumbnailData, thumbType, fileName);
501 if (err != E_OK) {
502 MEDIA_ERR_LOG("GetAvailableFile failed, path: %{public}s", DfxUtils::GetSafePath(thumbnailData.path).c_str());
503 return err;
504 }
505 bool isLocalThumbnailAvailable = IsLocalThumbnailAvailable(thumbnailData, thumbType);
506 DfxTimer dfxTimer(thumbType == ThumbnailType::LCD ? DfxType::CLOUD_LCD_OPEN : DfxType::CLOUD_DEFAULT_OPEN,
507 INVALID_DFX, thumbType == ThumbnailType::LCD ? CLOUD_LCD_TIME_OUT : CLOUD_DEFAULT_TIME_OUT, false);
508
509 string absFilePath;
510 if (!PathToRealPath(fileName, absFilePath)) {
511 MEDIA_ERR_LOG("file is not real path, file path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
512 return E_ERR;
513 }
514
515 auto fd = open(absFilePath.c_str(), O_RDONLY);
516 dfxTimer.End();
517 if (fd < 0) {
518 DfxManager::GetInstance()->HandleThumbnailError(absFilePath,
519 thumbType == ThumbnailType::LCD ? DfxType::CLOUD_LCD_OPEN : DfxType::CLOUD_DEFAULT_OPEN, -errno);
520 return -errno;
521 }
522 if (thumbnailData.isOpeningCloudFile && thumbnailData.orientation != 0) {
523 if (thumbnailData.mediaType == MEDIA_TYPE_VIDEO) {
524 MEDIA_INFO_LOG("No need to rotate video file, path: %{public}s",
525 DfxUtils::GetSafePath(thumbnailData.path).c_str());
526 thumbnailData.orientation = 0;
527 }
528 IThumbnailHelper::DoRotateThumbnailEx(opts, thumbnailData, fd, thumbType);
529 fileName = GetThumbnailPath(thumbnailData.path,
530 thumbType == ThumbnailType::LCD ? THUMBNAIL_LCD_SUFFIX : THUMBNAIL_THUMB_SUFFIX);
531 if (!PathToRealPath(fileName, absFilePath)) {
532 MEDIA_ERR_LOG("file is not real path, file path: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
533 return E_ERR;
534 }
535
536 fd = open(absFilePath.c_str(), O_RDONLY);
537 if (fd < 0) {
538 MEDIA_ERR_LOG("Rotate thumb failed, path: %{public}s", DfxUtils::GetSafePath(thumbnailData.path).c_str());
539 DfxManager::GetInstance()->HandleThumbnailError(absFilePath,
540 thumbType == ThumbnailType::LCD ? DfxType::CLOUD_LCD_OPEN : DfxType::CLOUD_DEFAULT_OPEN, -errno);
541 return -errno;
542 }
543 }
544 UpdateThumbStatus(opts, thumbType, thumbnailData, err, isLocalThumbnailAvailable);
545 return fd;
546 }
547
UpgradeThumbnailBackground(ThumbRdbOpt & opts,bool isWifiConnected)548 int32_t ThumbnailGenerateHelper::UpgradeThumbnailBackground(ThumbRdbOpt &opts, bool isWifiConnected)
549 {
550 if (opts.store == nullptr) {
551 MEDIA_ERR_LOG("rdbStore is not init");
552 return E_ERR;
553 }
554
555 vector<ThumbnailData> infos;
556 int32_t err = GetThumbnailDataNeedUpgrade(opts, infos, isWifiConnected);
557 if (err != E_OK) {
558 MEDIA_ERR_LOG("Failed to GetThumbnailDataNeedUpgrade %{public}d", err);
559 return err;
560 }
561 if (infos.empty()) {
562 MEDIA_DEBUG_LOG("No need upgrade thumbnail.");
563 return E_OK;
564 }
565 MEDIA_INFO_LOG("Will upgrade %{public}zu photo thumbnails, wifi: %{public}d.", infos.size(), isWifiConnected);
566 for (uint32_t i = 0; i < infos.size(); i++) {
567 opts.row = infos[i].id;
568 ThumbnailUtils::RecordStartGenerateStats(infos[i].stats, GenerateScene::UPGRADE, LoadSourceType::LOCAL_PHOTO);
569 infos[i].loaderOpts.loadingStates = (infos[i].mediaType == MEDIA_TYPE_VIDEO) ?
570 SourceLoader::UPGRADE_VIDEO_SOURCE_LOADING_STATES : SourceLoader::UPGRADE_SOURCE_LOADING_STATES;
571 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateLcdAndThumbnail,
572 opts, infos[i], ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::LOW);
573 }
574 return E_OK;
575 }
576
RestoreAstcDualFrame(ThumbRdbOpt & opts)577 int32_t ThumbnailGenerateHelper::RestoreAstcDualFrame(ThumbRdbOpt &opts)
578 {
579 if (opts.store == nullptr) {
580 MEDIA_ERR_LOG("rdbStore is not init");
581 return E_ERR;
582 }
583
584 vector<ThumbnailData> infos;
585 int32_t err = 0;
586 if (!ThumbnailUtils::QueryNoAstcInfosRestored(opts, infos, err)) {
587 MEDIA_ERR_LOG("Failed to QueryNoAstcInfosRestored %{public}d", err);
588 return err;
589 }
590 if (infos.empty()) {
591 MEDIA_INFO_LOG("No photos need resotre astc.");
592 return E_OK;
593 }
594
595 MEDIA_INFO_LOG("create astc for restored dual frame photos count:%{public}zu", infos.size());
596
597 for (auto &info : infos) {
598 opts.row = info.id;
599 if (!info.isLocalFile) {
600 MEDIA_INFO_LOG("skip restoring cloud photo astc path:%{public}s", DfxUtils::GetSafePath(info.path).c_str());
601 continue;
602 }
603 info.loaderOpts.loadingStates = SourceLoader::LOCAL_SOURCE_LOADING_STATES;
604 ThumbnailUtils::RecordStartGenerateStats(info.stats, GenerateScene::RESTORE, LoadSourceType::LOCAL_PHOTO);
605 IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::CreateThumbnail, opts, info,
606 ThumbnailTaskType::FOREGROUND, ThumbnailTaskPriority::MID);
607 }
608
609 MEDIA_INFO_LOG("create astc for restored dual frame photos finished");
610 return E_OK;
611 }
612
GetThumbnailDataNeedUpgrade(ThumbRdbOpt & opts,std::vector<ThumbnailData> & outDatas,bool isWifiConnected)613 int32_t ThumbnailGenerateHelper::GetThumbnailDataNeedUpgrade(ThumbRdbOpt &opts, std::vector<ThumbnailData> &outDatas,
614 bool isWifiConnected)
615 {
616 int32_t err = E_ERR;
617 if (!ThumbnailUtils::QueryUpgradeThumbnailInfos(opts, outDatas, isWifiConnected, err)) {
618 MEDIA_ERR_LOG("Failed to QueryUpgradeThumbnailInfos %{public}d", err);
619 return err;
620 }
621 return E_OK;
622 }
623
CheckMonthAndYearKvStoreValid(ThumbRdbOpt & opts)624 void ThumbnailGenerateHelper::CheckMonthAndYearKvStoreValid(ThumbRdbOpt &opts)
625 {
626 bool isMonthKvStoreValid = MediaLibraryKvStoreManager::GetInstance().IsKvStoreValid(KvStoreValueType::MONTH_ASTC);
627 bool isYearKvStoreValid = MediaLibraryKvStoreManager::GetInstance().IsKvStoreValid(KvStoreValueType::YEAR_ASTC);
628 if (isMonthKvStoreValid && isYearKvStoreValid) {
629 return;
630 }
631
632 if (opts.store == nullptr) {
633 MEDIA_ERR_LOG("rdbStore is not init");
634 return;
635 }
636
637 MEDIA_INFO_LOG("KvStore is invalid, start update rdb");
638 if (opts.store->ExecuteSql(SQL_REFRESH_THUMBNAIL_READY) != NativeRdb::E_OK) {
639 MEDIA_ERR_LOG("Update rdb failed");
640 return;
641 }
642 MEDIA_INFO_LOG("Update rdb successfully");
643
644 if (!isMonthKvStoreValid) {
645 MediaLibraryKvStoreManager::GetInstance().RebuildInvalidKvStore(KvStoreValueType::MONTH_ASTC);
646 }
647
648 if (!isYearKvStoreValid) {
649 MediaLibraryKvStoreManager::GetInstance().RebuildInvalidKvStore(KvStoreValueType::YEAR_ASTC);
650 }
651
652 Acl::AclSetDatabase();
653 MEDIA_INFO_LOG("RebuildInvalidKvStore finish, isMonthKvStoreValid: %{public}d, isYearKvStoreValid: %{public}d",
654 isMonthKvStoreValid, isYearKvStoreValid);
655 }
656 } // namespace Media
657 } // namespace OHOS
658