• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define MLOG_TAG "Thumbnail"
16 
17 #include "thumbnail_generate_helper.h"
18 
19 #include <fcntl.h>
20 
21 #include "acl.h"
22 #include "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