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