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