1 /*
2  * Copyright (C) 2022-2023 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 
16 #define MLOG_TAG "Thumbnail"
17 
18 #include "thumbnail_utils.h"
19 
20 #include <fcntl.h>
21 #include <malloc.h>
22 #include <sys/stat.h>
23 
24 #include "cloud_sync_helper.h"
25 #include "datashare_helper.h"
26 #include "datashare_abs_result_set.h"
27 #ifdef DISTRIBUTED
28 #include "device_manager.h"
29 #endif
30 #include "dfx_utils.h"
31 #include "directory_ex.h"
32 #include "distributed_kv_data_manager.h"
33 #include "hitrace_meter.h"
34 #include "image_packer.h"
35 #include "ipc_skeleton.h"
36 #include "iservice_registry.h"
37 #include "media_column.h"
38 #ifdef DISTRIBUTED
39 #include "media_device_column.h"
40 #endif
41 #include "media_exif.h"
42 #include "media_remote_thumbnail_column.h"
43 #include "medialibrary_common_utils.h"
44 #include "medialibrary_errno.h"
45 #include "medialibrary_kvstore_manager.h"
46 #include "medialibrary_sync_operation.h"
47 #include "medialibrary_tracer.h"
48 #include "media_file_utils.h"
49 #include "media_log.h"
50 #include "mimetype_utils.h"
51 #include "parameter.h"
52 #include "post_proc.h"
53 #include "rdb_errno.h"
54 #include "result_set_utils.h"
55 #include "thumbnail_const.h"
56 #include "thumbnail_source_loading.h"
57 #include "unique_fd.h"
58 #include "wifi_device.h"
59 #include "post_event_utils.h"
60 #include "dfx_manager.h"
61 #include "image_format_convert.h"
62 
63 using namespace std;
64 using namespace OHOS::DistributedKv;
65 using namespace OHOS::NativeRdb;
66 
67 namespace OHOS {
68 namespace Media {
69 
70 static constexpr int STORAGE_MANAGER_MANAGER_ID = 5003;
71 static const std::string CLOUD_DATASHARE_URI = "datashareproxy://com.huawei.hmos.clouddrive/cloud_sp?Proxy=true";
72 
73 #ifdef DISTRIBUTED
DeleteDistributeLcdData(ThumbRdbOpt & opts,ThumbnailData & thumbnailData)74 bool ThumbnailUtils::DeleteDistributeLcdData(ThumbRdbOpt &opts, ThumbnailData &thumbnailData)
75 {
76     if (thumbnailData.lcdKey.empty()) {
77         MEDIA_ERR_LOG("lcd Key is empty");
78         return false;
79     }
80 
81     if (IsImageExist(thumbnailData.lcdKey, opts.networkId, opts.kvStore)) {
82         if (!RemoveDataFromKv(opts.kvStore, thumbnailData.lcdKey)) {
83             MEDIA_ERR_LOG("ThumbnailUtils::RemoveDataFromKv faild");
84             return false;
85         }
86         if (!CleanDistributeLcdInfo(opts)) {
87             return false;
88         }
89     }
90 
91     return true;
92 }
93 #endif
94 
GetThumbnailSuffix(ThumbnailType type)95 std::string ThumbnailUtils::GetThumbnailSuffix(ThumbnailType type)
96 {
97     string suffix;
98     switch (type) {
99         case ThumbnailType::THUMB:
100             suffix = THUMBNAIL_THUMB_SUFFIX;
101             break;
102         case ThumbnailType::THUMB_ASTC:
103             suffix = THUMBNAIL_THUMBASTC_SUFFIX;
104             break;
105         case ThumbnailType::LCD:
106             suffix = THUMBNAIL_LCD_SUFFIX;
107             break;
108         default:
109             return "";
110     }
111     return suffix;
112 }
113 
DeleteThumbFile(ThumbnailData & data,ThumbnailType type)114 bool ThumbnailUtils::DeleteThumbFile(ThumbnailData &data, ThumbnailType type)
115 {
116     string fileName = GetThumbnailPath(data.path, GetThumbnailSuffix(type));
117     if (!MediaFileUtils::DeleteFile(fileName)) {
118         MEDIA_ERR_LOG("delete file faild %{public}d", errno);
119         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, -errno},
120             {KEY_OPT_FILE, fileName}, {KEY_OPT_TYPE, OptType::THUMB}};
121         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
122         return false;
123     }
124     return true;
125 }
126 
DeleteThumbExDir(ThumbnailData & data)127 bool ThumbnailUtils::DeleteThumbExDir(ThumbnailData &data)
128 {
129     string fileName = GetThumbnailPath(data.path, THUMBNAIL_THUMB_EX_SUFFIX);
130     string dirName = MediaFileUtils::GetParentPath(fileName);
131     if (access(dirName.c_str(), F_OK) != 0) {
132         MEDIA_INFO_LOG("No need to delete THM_EX, directory not exists path: %{public}s, id: %{public}s",
133             DfxUtils::GetSafePath(dirName).c_str(), data.id.c_str());
134         return true;
135     }
136     if (!MediaFileUtils::DeleteDir(dirName)) {
137         MEDIA_INFO_LOG("Failed to delete THM_EX directory, path: %{public}s, id: %{public}s",
138             DfxUtils::GetSafePath(dirName).c_str(), data.id.c_str());
139         return false;
140     }
141     return true;
142 }
143 
LoadAudioFileInfo(shared_ptr<AVMetadataHelper> avMetadataHelper,ThumbnailData & data,Size & desiredSize,uint32_t & errCode)144 bool ThumbnailUtils::LoadAudioFileInfo(shared_ptr<AVMetadataHelper> avMetadataHelper, ThumbnailData &data,
145     Size &desiredSize, uint32_t &errCode)
146 {
147     if (avMetadataHelper == nullptr || avMetadataHelper->FetchArtPicture() == nullptr) {
148         MEDIA_ERR_LOG("FetchArtPicture failed!");
149         return false;
150     }
151 
152     auto audioPicMemory = avMetadataHelper->FetchArtPicture();
153     SourceOptions opts;
154     unique_ptr<ImageSource> audioImageSource = ImageSource::CreateImageSource(audioPicMemory->GetBase(),
155         audioPicMemory->GetSize(), opts, errCode);
156     if (audioImageSource == nullptr) {
157         MEDIA_ERR_LOG("Failed to create image source! path %{public}s errCode %{public}d",
158             DfxUtils::GetSafePath(data.path).c_str(), errCode);
159         return false;
160     }
161 
162     ImageInfo imageInfo;
163     errCode = audioImageSource->GetImageInfo(0, imageInfo);
164     if (errCode != E_OK) {
165         MEDIA_ERR_LOG("Failed to get image info, path: %{public}s err: %{public}d",
166             DfxUtils::GetSafePath(data.path).c_str(), errCode);
167         return false;
168     }
169     data.stats.sourceWidth = imageInfo.size.width;
170     data.stats.sourceHeight = imageInfo.size.height;
171 
172     DecodeOptions decOpts;
173     decOpts.desiredSize = ConvertDecodeSize(data, imageInfo.size, desiredSize);
174     decOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
175     auto pixelMapPtr = audioImageSource->CreatePixelMap(decOpts, errCode);
176     std::shared_ptr<PixelMap> pixelMap = std::move(pixelMapPtr);
177     if ((errCode != E_OK) || (pixelMap == nullptr)) {
178         MEDIA_ERR_LOG("Av meta data helper fetch frame at time failed");
179         if (errCode != E_OK) {
180             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
181                 {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, data.path},
182                 {KEY_OPT_TYPE, OptType::THUMB}};
183             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
184         }
185         return false;
186     }
187     data.source.SetPixelMap(pixelMap);
188     return true;
189 }
190 
LoadAudioFile(ThumbnailData & data,Size & desiredSize)191 bool ThumbnailUtils::LoadAudioFile(ThumbnailData &data, Size &desiredSize)
192 {
193     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
194     string path = data.path;
195     int32_t err = SetSource(avMetadataHelper, path);
196     if (err != E_OK) {
197         MEDIA_ERR_LOG("Av meta data helper set source failed %{public}d", err);
198         return false;
199     }
200     uint32_t errCode = 0;
201     if (!LoadAudioFileInfo(avMetadataHelper, data, desiredSize, errCode)) {
202         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
203             {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
204         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
205         return false;
206     }
207     return true;
208 }
209 
LoadVideoFile(ThumbnailData & data,Size & desiredSize)210 bool ThumbnailUtils::LoadVideoFile(ThumbnailData &data, Size &desiredSize)
211 {
212     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
213     string path = data.path;
214     int32_t err = SetSource(avMetadataHelper, path);
215     if (err != 0) {
216         return false;
217     }
218     int32_t videoWidth = 0;
219     int32_t videoHeight = 0;
220     if (!ParseVideoSize(avMetadataHelper, videoWidth, videoHeight)) {
221         return false;
222     }
223     PixelMapParams param;
224     param.colorFormat = PixelFormat::RGBA_8888;
225     ConvertDecodeSize(data, {videoWidth, videoHeight}, desiredSize);
226     param.dstWidth = desiredSize.width;
227     param.dstHeight = desiredSize.height;
228     std::shared_ptr<PixelMap> pixelMap;
229     pixelMap = avMetadataHelper->FetchFrameYuv(AV_FRAME_TIME, AVMetadataQueryOption::AV_META_QUERY_NEXT_SYNC,
230         param);
231     if (pixelMap == nullptr) {
232         DfxManager::GetInstance()->HandleThumbnailError(path, DfxType::AV_FETCH_FRAME, err);
233         return false;
234     }
235     if (pixelMap->GetPixelFormat() == PixelFormat::YCBCR_P010) {
236         uint32_t ret = ImageFormatConvert::ConvertImageFormat(pixelMap, PixelFormat::RGBA_1010102);
237         if (ret != E_OK) {
238             MEDIA_ERR_LOG("PixelMapYuv10ToRGBA_1010102: source ConvertImageFormat fail");
239             return false;
240         }
241     }
242 
243     data.source.SetPixelMap(pixelMap);
244     data.orientation = 0;
245     data.stats.sourceWidth = pixelMap->GetWidth();
246     data.stats.sourceHeight = pixelMap->GetHeight();
247     DfxManager::GetInstance()->HandleHighMemoryThumbnail(path, MEDIA_TYPE_VIDEO, videoWidth, videoHeight);
248     return true;
249 }
250 
ParseVideoSize(std::shared_ptr<AVMetadataHelper> & avMetadataHelper,int32_t & videoWidth,int32_t & videoHeight)251 bool ThumbnailUtils::ParseVideoSize(std::shared_ptr<AVMetadataHelper> &avMetadataHelper,
252     int32_t &videoWidth, int32_t &videoHeight)
253 {
254     auto resultMap = avMetadataHelper->ResolveMetadata();
255     if (resultMap.empty()) {
256         MEDIA_ERR_LOG("map of video size is empty");
257         return false;
258     }
259     int32_t rotation = 0;
260     const std::string strOfRotation = resultMap.at(AVMetadataCode::AV_KEY_VIDEO_ORIENTATION);
261     if (strOfRotation.empty()) {
262         // The field of rotation may be empty, and if it is empty, it means rotation is zero
263         MEDIA_INFO_LOG("rotation is zero");
264     } else if (!ConvertStrToInt32(strOfRotation, rotation)) {
265         MEDIA_ERR_LOG("Parse rotation from resultmap error");
266         return false;
267     }
268 
269     bool needRevolve = ((rotation + VERTICAL_ANGLE) % STRAIGHT_ANGLE != 0);
270     if (!ConvertStrToInt32(resultMap.at(AVMetadataCode::AV_KEY_VIDEO_WIDTH),
271         needRevolve ? videoWidth : videoHeight)) {
272         MEDIA_ERR_LOG("Parse width from resultmap error");
273         return false;
274     }
275     if (!ConvertStrToInt32(resultMap.at(AVMetadataCode::AV_KEY_VIDEO_HEIGHT),
276         needRevolve ? videoHeight : videoWidth)) {
277         MEDIA_ERR_LOG("Parse height from resultmap error");
278         return false;
279     }
280     return true;
281 }
282 
283 // gen pixelmap from data.souce.pixelMapSource, should ensure source is not null
GenTargetPixelmap(ThumbnailData & data,const Size & desiredSize)284 bool ThumbnailUtils::GenTargetPixelmap(ThumbnailData &data, const Size &desiredSize)
285 {
286     MediaLibraryTracer tracer;
287     tracer.Start("GenTargetPixelmap");
288     auto pixelMap = data.source.GetPixelMap();
289     if (pixelMap == nullptr) {
290         return false;
291     }
292 
293     if (!ScaleFastThumb(data, desiredSize)) {
294         return false;
295     }
296 
297     float widthScale = (1.0f * desiredSize.width) / pixelMap->GetWidth();
298     float heightScale = (1.0f * desiredSize.height) / pixelMap->GetHeight();
299     pixelMap->scale(widthScale, heightScale);
300     return true;
301 }
302 
ScaleTargetPixelMap(std::shared_ptr<PixelMap> & dataSource,const Size & targetSize,const AntiAliasingOption & option)303 bool ThumbnailUtils::ScaleTargetPixelMap(std::shared_ptr<PixelMap> &dataSource, const Size &targetSize,
304     const AntiAliasingOption &option)
305 {
306     MediaLibraryTracer tracer;
307     tracer.Start("ImageSource::ScaleTargetPixelMap");
308 
309     PostProc postProc;
310     if (!postProc.ScalePixelMapEx(targetSize, *dataSource, option)) {
311         MEDIA_ERR_LOG("Fail to scale to target thumbnail, ScalePixelMapEx failed, targetSize: %{public}d * %{public}d",
312             targetSize.width, targetSize.height);
313         return false;
314     }
315     return true;
316 }
317 
CenterScaleEx(std::shared_ptr<PixelMap> & dataSource,const Size & desiredSize,const std::string path)318 bool ThumbnailUtils::CenterScaleEx(std::shared_ptr<PixelMap> &dataSource, const Size &desiredSize,
319     const std::string path)
320 {
321     if (dataSource->GetHeight() * dataSource->GetWidth() == 0) {
322         MEDIA_ERR_LOG("Invalid source size, ScalePixelMapEx failed, path: %{public}s",
323             DfxUtils::GetSafePath(path).c_str());
324         return false;
325     }
326     float sourceScale = static_cast<float>(dataSource->GetHeight()) / static_cast<float>(dataSource->GetWidth());
327     float scale = 1.0f;
328     if (sourceScale <= 1.0f) {
329         scale = static_cast<float>(desiredSize.height) / static_cast<float>(dataSource->GetHeight());
330     } else {
331         scale = static_cast<float>(desiredSize.width) / static_cast<float>(dataSource->GetWidth());
332     }
333 
334     MediaLibraryTracer tracer;
335     tracer.Start("CenterScaleEx");
336     if (std::abs(scale - 1.0f) > FLOAT_EPSILON) {
337         Size targetSize = {
338             static_cast<int32_t>(scale * dataSource->GetWidth()),
339             static_cast<int32_t>(scale * dataSource->GetHeight())
340         };
341         if (!ScaleTargetPixelMap(dataSource, targetSize, Media::AntiAliasingOption::GAUSS)) {
342             MEDIA_ERR_LOG("Fail in CenterScaleEx, ScalePixelMapEx failed, path: %{public}s",
343                 DfxUtils::GetSafePath(path).c_str());
344             return false;
345         }
346     }
347 
348     MediaLibraryTracer innerTracer;
349     innerTracer.Start("CenterScale");
350     PostProc postProc;
351     if (!postProc.CenterScale(desiredSize, *dataSource)) {
352         MEDIA_ERR_LOG("Fail in CenterScaleEx, CenterScale failed, path: %{public}s",
353             DfxUtils::GetSafePath(path).c_str());
354         return false;
355     }
356     return true;
357 }
358 
LoadImageFile(ThumbnailData & data,Size & desiredSize)359 bool ThumbnailUtils::LoadImageFile(ThumbnailData &data, Size &desiredSize)
360 {
361     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
362     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
363 
364     SourceLoader sourceLoader(desiredSize, data);
365     return sourceLoader.RunLoading();
366 }
367 
CompressImage(shared_ptr<PixelMap> & pixelMap,vector<uint8_t> & data,bool isHigh,bool isAstc,bool forceSdr)368 bool ThumbnailUtils::CompressImage(shared_ptr<PixelMap> &pixelMap, vector<uint8_t> &data, bool isHigh, bool isAstc,
369     bool forceSdr)
370 {
371     PackOption option = {
372         .format = isAstc ? THUMBASTC_FORMAT : THUMBNAIL_FORMAT,
373         .quality = isAstc ? ASTC_LOW_QUALITY : (isHigh ? THUMBNAIL_HIGH : THUMBNAIL_MID),
374         .numberHint = NUMBER_HINT_1,
375         .desiredDynamicRange = forceSdr ? EncodeDynamicRange::SDR :EncodeDynamicRange::AUTO
376     };
377     data.resize(max(pixelMap->GetByteCount(), MIN_COMPRESS_BUF_SIZE));
378 
379     MediaLibraryTracer tracer;
380     tracer.Start("imagePacker.StartPacking");
381     ImagePacker imagePacker;
382     uint32_t err = imagePacker.StartPacking(data.data(), data.size(), option);
383     tracer.Finish();
384     if (err != E_OK) {
385         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
386         return false;
387     }
388 
389     tracer.Start("imagePacker.AddImage");
390     err = imagePacker.AddImage(*pixelMap);
391     tracer.Finish();
392     if (err != E_OK) {
393         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
394         return false;
395     }
396 
397     tracer.Start("imagePacker.FinalizePacking");
398     int64_t packedSize = 0;
399     err = imagePacker.FinalizePacking(packedSize);
400     if (err != E_OK) {
401         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
402         return false;
403     }
404 
405     data.resize(packedSize);
406     return true;
407 }
408 
CheckAfterPacking(const std::string & tempOutputPath,const std::string & outputPath)409 bool CheckAfterPacking(const std::string &tempOutputPath, const std::string &outputPath)
410 {
411     size_t size = -1;
412     MediaFileUtils::GetFileSize(tempOutputPath, size);
413     if (size == 0 && !MediaFileUtils::DeleteFile(tempOutputPath)) {
414         MEDIA_ERR_LOG("CompressPicture failed, failed to delete temp filters file: %{public}s",
415             DfxUtils::GetSafePath(tempOutputPath).c_str());
416         return false;
417     }
418     int ret = rename(tempOutputPath.c_str(), outputPath.c_str());
419     if (ret != E_SUCCESS) {
420         MEDIA_ERR_LOG("CompressPicture failed, failed to rename temp filters file: %{public}s",
421             DfxUtils::GetSafePath(tempOutputPath).c_str());
422         return false;
423     }
424     if (MediaFileUtils::IsFileExists(tempOutputPath)) {
425         MEDIA_INFO_LOG("file: %{public}s exists, needs to be deleted", DfxUtils::GetSafePath(tempOutputPath).c_str());
426         if (!MediaFileUtils::DeleteFile(tempOutputPath)) {
427             MEDIA_ERR_LOG("delete file: %{public}s failed", DfxUtils::GetSafePath(tempOutputPath).c_str());
428         }
429     }
430     return true;
431 }
432 
CompressPicture(ThumbnailData & data,bool isSourceEx)433 bool ThumbnailUtils::CompressPicture(ThumbnailData &data, bool isSourceEx)
434 {
435     MEDIA_INFO_LOG("CompressPicture %{public}s", DfxUtils::GetSafePath(data.path).c_str());
436     auto outputPath = GetThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
437     auto picture = isSourceEx ? data.source.GetPictureEx() : data.source.GetPicture();
438     if (picture == nullptr) {
439         MEDIA_ERR_LOG("CompressPicture failed, source is nullptr, path: %{public}s",
440             DfxUtils::GetSafePath(data.path).c_str());
441         return false;
442     }
443     Media::ImagePacker imagePacker;
444     PackOption option = {
445         .format = THUMBNAIL_FORMAT,
446         .quality = THUMBNAIL_MID,
447         .numberHint = NUMBER_HINT_1,
448         .desiredDynamicRange = EncodeDynamicRange::AUTO,
449         .needsPackProperties = false
450     };
451     int ret = SaveFileCreateDir(data.path, isSourceEx ? THUMBNAIL_LCD_EX_SUFFIX : THUMBNAIL_LCD_SUFFIX, outputPath);
452     if (ret != E_OK) {
453         MEDIA_ERR_LOG("CompressPicture failed, SaveFileCreateDir failed, path: %{public}s, isSourceEx: %{public}d",
454             DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
455         return false;
456     }
457     size_t lastSlash = outputPath.rfind('/');
458     if (lastSlash == string::npos || outputPath.size() <= lastSlash + 1) {
459         MEDIA_ERR_LOG("CompressPicture failed, failed to check outputPath: %{public}s, isSourceEx: %{public}d",
460             DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
461         return false;
462     }
463     string tempOutputPath = outputPath.substr(0, lastSlash) + "/temp_" + outputPath.substr(lastSlash + 1);
464     ret = MediaFileUtils::CreateAsset(tempOutputPath);
465     if (ret != E_SUCCESS) {
466         MEDIA_ERR_LOG("CompressPicture failed, failed to create temp filter file: %{public}s, isSourceEx: %{public}d",
467             DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
468         return false;
469     }
470     imagePacker.StartPacking(tempOutputPath, option);
471     imagePacker.AddPicture(*(picture));
472     imagePacker.FinalizePacking();
473     CheckAfterPacking(tempOutputPath, outputPath);
474     return true;
475 }
476 
QueryThumbnailSet(ThumbRdbOpt & opts)477 shared_ptr<ResultSet> ThumbnailUtils::QueryThumbnailSet(ThumbRdbOpt &opts)
478 {
479     vector<string> column = {
480         MEDIA_DATA_DB_ID,
481         MEDIA_DATA_DB_FILE_PATH,
482         MEDIA_DATA_DB_MEDIA_TYPE,
483     };
484 
485     vector<string> selectionArgs;
486     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + opts.row;
487 
488     RdbPredicates rdbPredicates(opts.table);
489     rdbPredicates.SetWhereClause(strQueryCondition);
490     rdbPredicates.SetWhereArgs(selectionArgs);
491     if (opts.store == nullptr) {
492         MEDIA_ERR_LOG("opts.store is nullptr");
493         return nullptr;
494     }
495     return opts.store->QueryByStep(rdbPredicates, column);
496 }
497 
QueryThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)498 shared_ptr<ResultSet> ThumbnailUtils::QueryThumbnailInfo(ThumbRdbOpt &opts,
499     ThumbnailData &data, int &err)
500 {
501     vector<string> column = {
502         MEDIA_DATA_DB_ID,
503         MEDIA_DATA_DB_FILE_PATH,
504         MEDIA_DATA_DB_MEDIA_TYPE,
505     };
506     MediaLibraryTracer tracer;
507     tracer.Start("QueryThumbnailInfo");
508     auto resultSet = QueryThumbnailSet(opts);
509     if (!CheckResultSetCount(resultSet, err)) {
510         return nullptr;
511     }
512 
513     err = resultSet->GoToFirstRow();
514     if (err != E_OK) {
515         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
516             {KEY_OPT_TYPE, OptType::THUMB}};
517         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
518         return nullptr;
519     }
520 
521     ParseQueryResult(resultSet, data, err, column);
522     return resultSet;
523 }
524 
QueryLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)525 bool ThumbnailUtils::QueryLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
526 {
527     vector<string> column = {
528         MEDIA_DATA_DB_ID,
529     };
530     RdbPredicates rdbPredicates(opts.table);
531     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
532         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
533     }
534     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
535     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
536     if (opts.store == nullptr) {
537         MEDIA_ERR_LOG("opts.store is nullptr");
538         return false;
539     }
540     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
541     if (resultSet == nullptr) {
542         MEDIA_ERR_LOG("ResultSet is nullptr");
543         return false;
544     }
545     int rowCount = 0;
546     err = resultSet->GetRowCount(rowCount);
547     resultSet.reset();
548     if (err != E_OK) {
549         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
550         return false;
551     }
552     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
553     if (rowCount <= 0) {
554         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
555         rowCount = 0;
556     }
557 
558     outLcdCount = rowCount;
559     return true;
560 }
561 
QueryLcdCountByTime(const int64_t & time,const bool & before,ThumbRdbOpt & opts,int & outLcdCount,int & err)562 bool ThumbnailUtils::QueryLcdCountByTime(const int64_t &time, const bool &before, ThumbRdbOpt &opts, int &outLcdCount,
563     int &err)
564 {
565     vector<string> column = {
566         MEDIA_DATA_DB_ID,
567     };
568     RdbPredicates rdbPredicates(opts.table);
569     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
570         if (before) {
571             rdbPredicates.LessThanOrEqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
572         } else {
573             rdbPredicates.GreaterThan(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
574         }
575     }
576     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
577     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
578     if (opts.store == nullptr) {
579         MEDIA_ERR_LOG("opts.store is nullptr");
580         return false;
581     }
582     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
583     if (resultSet == nullptr) {
584         MEDIA_ERR_LOG("ResultSet is nullptr");
585         return false;
586     }
587     int rowCount = 0;
588     err = resultSet->GetRowCount(rowCount);
589     resultSet.reset();
590     if (err != E_OK) {
591         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
592         return false;
593     }
594     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
595     if (rowCount <= 0) {
596         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
597         rowCount = 0;
598     }
599 
600     outLcdCount = rowCount;
601     return true;
602 }
603 
QueryDistributeLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)604 bool ThumbnailUtils::QueryDistributeLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
605 {
606     vector<string> column = {
607         REMOTE_THUMBNAIL_DB_ID,
608     };
609     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
610     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
611     rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
612     if (opts.store == nullptr) {
613         MEDIA_ERR_LOG("opts.store is nullptr");
614         return false;
615     }
616     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
617     if (resultSet == nullptr) {
618         return false;
619     }
620     int rowCount = 0;
621     err = resultSet->GetRowCount(rowCount);
622     resultSet.reset();
623     if (err != E_OK) {
624         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
625         return false;
626     }
627     MEDIA_INFO_LOG("rowCount is %{public}d", rowCount);
628     if (rowCount <= 0) {
629         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
630         rowCount = 0;
631     }
632     outLcdCount = rowCount;
633     return true;
634 }
635 
636 #ifdef DISTRIBUTED
QueryAgingDistributeLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailData> & infos,int & err)637 bool ThumbnailUtils::QueryAgingDistributeLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
638     vector<ThumbnailData> &infos, int &err)
639 {
640     vector<string> column = {
641         REMOTE_THUMBNAIL_DB_FILE_ID,
642         MEDIA_DATA_DB_LCD
643     };
644     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
645     rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
646     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
647 
648     rdbPredicates.Limit(LcdLimit);
649     if (opts.store == nullptr) {
650         MEDIA_ERR_LOG("opts.store is nullptr");
651         return false;
652     }
653     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
654     if (!CheckResultSetCount(resultSet, err)) {
655         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
656         return false;
657     }
658 
659     err = resultSet->GoToFirstRow();
660     if (err != E_OK) {
661         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
662         return false;
663     }
664 
665     ThumbnailData data;
666     do {
667         ParseQueryResult(resultSet, data, err, column);
668         if (!data.lcdKey.empty()) {
669             infos.push_back(data);
670         }
671     } while (resultSet->GoToNextRow() == E_OK);
672     return true;
673 }
674 #endif
675 
QueryAgingLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailData> & infos,int & err)676 bool ThumbnailUtils::QueryAgingLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
677     vector<ThumbnailData> &infos, int &err)
678 {
679     vector<string> column = {
680         MEDIA_DATA_DB_ID,
681         MEDIA_DATA_DB_FILE_PATH,
682         MEDIA_DATA_DB_MEDIA_TYPE,
683     };
684     RdbPredicates rdbPredicates(opts.table);
685     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
686     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
687 
688     rdbPredicates.Limit(LcdLimit);
689     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
690         rdbPredicates.OrderByAsc(PhotoColumn::PHOTO_LAST_VISIT_TIME);
691     }
692     if (opts.store == nullptr) {
693         MEDIA_ERR_LOG("opts.store is nullptr");
694         return false;
695     }
696     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
697     if (!CheckResultSetCount(resultSet, err)) {
698         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
699         return false;
700     }
701 
702     err = resultSet->GoToFirstRow();
703     if (err != E_OK) {
704         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
705         return false;
706     }
707 
708     ThumbnailData data;
709     do {
710         ParseQueryResult(resultSet, data, err, column);
711         if (!data.path.empty()) {
712             infos.push_back(data);
713         }
714     } while (resultSet->GoToNextRow() == E_OK);
715     return true;
716 }
717 
QueryNoLcdInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)718 bool ThumbnailUtils::QueryNoLcdInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
719 {
720     vector<string> column = {
721         MEDIA_DATA_DB_ID,
722         MEDIA_DATA_DB_FILE_PATH,
723         MEDIA_DATA_DB_MEDIA_TYPE,
724         MEDIA_DATA_DB_POSITION,
725         MEDIA_DATA_DB_ORIENTATION,
726     };
727     RdbPredicates rdbPredicates(opts.table);
728     rdbPredicates.EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, "0");
729     rdbPredicates.EqualTo(PhotoColumn::PHOTO_POSITION, "1");
730     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
731     if (opts.store == nullptr) {
732         MEDIA_ERR_LOG("opts.store is nullptr");
733         return false;
734     }
735     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
736     if (!CheckResultSetCount(resultSet, err)) {
737         MEDIA_ERR_LOG("QueryNoLcdInfos failed %{public}d", err);
738         if (err == E_EMPTY_VALUES_BUCKET) {
739             return true;
740         }
741         return false;
742     }
743 
744     err = resultSet->GoToFirstRow();
745     if (err != E_OK) {
746         MEDIA_ERR_LOG("QueryNoLcdInfos failed GoToFirstRow %{public}d", err);
747         return false;
748     }
749 
750     ThumbnailData data;
751     do {
752         ParseQueryResult(resultSet, data, err, column);
753         if (!data.path.empty()) {
754             infos.push_back(data);
755         }
756     } while (resultSet->GoToNextRow() == E_OK);
757     return true;
758 }
759 
QueryLocalNoLcdInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)760 bool ThumbnailUtils::QueryLocalNoLcdInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
761 {
762     if (opts.store == nullptr) {
763         MEDIA_ERR_LOG("opts.store is nullptr");
764         return false;
765     }
766     vector<string> column = {
767         MEDIA_DATA_DB_ID,
768         MEDIA_DATA_DB_FILE_PATH,
769         MEDIA_DATA_DB_MEDIA_TYPE,
770     };
771     RdbPredicates rdbPredicates(opts.table);
772     rdbPredicates.EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, "0");
773     rdbPredicates.EqualTo(PhotoColumn::PHOTO_DIRTY, "1");
774     rdbPredicates.Limit(MAXIMUM_LCD_CHECK_NUM);
775     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
776     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
777     if (!CheckResultSetCount(resultSet, err)) {
778         MEDIA_ERR_LOG("QueryLocalNoLcdInfos failed %{public}d", err);
779         if (err == E_EMPTY_VALUES_BUCKET) {
780             return true;
781         }
782         return false;
783     }
784 
785     err = resultSet->GoToFirstRow();
786     if (err != E_OK) {
787         MEDIA_ERR_LOG("QueryLocalNoLcdInfos failed GoToFirstRow %{public}d", err);
788         return false;
789     }
790 
791     ThumbnailData data;
792     do {
793         ParseQueryResult(resultSet, data, err, column);
794         if (!data.path.empty()) {
795             infos.push_back(data);
796         }
797     } while (resultSet->GoToNextRow() == E_OK);
798     return true;
799 }
800 
QueryNoThumbnailInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)801 bool ThumbnailUtils::QueryNoThumbnailInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
802 {
803     vector<string> column = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_MEDIA_TYPE };
804     RdbPredicates rdbPredicates(opts.table);
805     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
806         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
807     }
808     if ((opts.table == PhotoColumn::PHOTOS_TABLE) || (opts.table == AudioColumn::AUDIOS_TABLE)) {
809         rdbPredicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, "0");
810     } else {
811         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
812     }
813     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
814     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
815     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
816     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
817         // Filter data that Only exists in Cloud to avoid cosuming data of downloading the original image
818         // meaning of Position: 1--only in local, 2--only in cloud, 3--both in local and cloud
819         rdbPredicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->
820             EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
821     }
822     rdbPredicates.Limit(THUMBNAIL_QUERY_MAX);
823     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
824     if (opts.store == nullptr) {
825         MEDIA_ERR_LOG("opts.store is nullptr");
826         return false;
827     }
828     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
829     if (!CheckResultSetCount(resultSet, err)) {
830         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
831         if (err == E_EMPTY_VALUES_BUCKET) {
832             return true;
833         }
834         return false;
835     }
836     err = resultSet->GoToFirstRow();
837     if (err != E_OK) {
838         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
839         return false;
840     }
841     ThumbnailData data;
842     do {
843         ParseQueryResult(resultSet, data, err, column);
844         if (!data.path.empty()) {
845             infos.push_back(data);
846         }
847     } while (resultSet->GoToNextRow() == E_OK);
848     return true;
849 }
850 
QueryUpgradeThumbnailInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,bool isWifiConnected,int & err)851 bool ThumbnailUtils::QueryUpgradeThumbnailInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos,
852     bool isWifiConnected, int &err)
853 {
854     vector<string> column = {
855         MEDIA_DATA_DB_ID,
856         MEDIA_DATA_DB_FILE_PATH,
857         MEDIA_DATA_DB_MEDIA_TYPE,
858         MEDIA_DATA_DB_DATE_ADDED,
859         MEDIA_DATA_DB_NAME,
860         MEDIA_DATA_DB_DATE_TAKEN,
861     };
862     RdbPredicates rdbPredicates(opts.table);
863     rdbPredicates.EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, std::to_string(
864         static_cast<int32_t>(ThumbnailReady::THUMB_UPGRADE)));
865     if (!isWifiConnected) {
866         rdbPredicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, "2");
867     }
868     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
869     if (opts.store == nullptr) {
870         MEDIA_ERR_LOG("opts.store is nullptr");
871         return false;
872     }
873     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
874     if (!CheckResultSetCount(resultSet, err)) {
875         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
876         if (err == E_EMPTY_VALUES_BUCKET) {
877             return true;
878         }
879         return false;
880     }
881 
882     err = resultSet->GoToFirstRow();
883     if (err != E_OK) {
884         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
885         return false;
886     }
887 
888     ThumbnailData data;
889     do {
890         ParseQueryResult(resultSet, data, err, column);
891         if (!data.path.empty()) {
892             infos.push_back(data);
893         }
894     } while (resultSet->GoToNextRow() == E_OK);
895     return true;
896 }
897 
QueryNoAstcInfosRestored(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)898 bool ThumbnailUtils::QueryNoAstcInfosRestored(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
899 {
900     vector<string> column = {
901         MEDIA_DATA_DB_ID,
902         MEDIA_DATA_DB_FILE_PATH,
903         MEDIA_DATA_DB_MEDIA_TYPE,
904         MEDIA_DATA_DB_DATE_ADDED,
905         MEDIA_DATA_DB_NAME,
906         MEDIA_DATA_DB_POSITION,
907         MEDIA_DATA_DB_DATE_TAKEN,
908     };
909     RdbPredicates rdbPredicates(opts.table);
910     rdbPredicates.EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "0");
911     rdbPredicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->
912         EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
913     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
914     rdbPredicates.Limit(ASTC_GENERATE_COUNT_AFTER_RESTORE);
915     if (opts.store == nullptr) {
916         MEDIA_ERR_LOG("opts.store is nullptr");
917         return false;
918     }
919     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
920     if (!CheckResultSetCount(resultSet, err)) {
921         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
922         if (err == E_EMPTY_VALUES_BUCKET) {
923             return true;
924         }
925         return false;
926     }
927 
928     err = resultSet->GoToFirstRow();
929     if (err != E_OK) {
930         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
931         return false;
932     }
933 
934     ThumbnailData data;
935     do {
936         ParseQueryResult(resultSet, data, err, column);
937         if (!data.path.empty()) {
938             infos.push_back(data);
939         }
940     } while (resultSet->GoToNextRow() == E_OK);
941     return true;
942 }
943 
QueryNoAstcInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)944 bool ThumbnailUtils::QueryNoAstcInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
945 {
946     vector<string> column = {
947         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_DATE_TAKEN,
948         MEDIA_DATA_DB_NAME, MEDIA_DATA_DB_POSITION, MEDIA_DATA_DB_ORIENTATION,
949     };
950     RdbPredicates rdbPredicates(opts.table);
951     rdbPredicates.BeginWrap()
952         ->EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "0")
953         ->Or()->EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "2")
954         ->Or()->EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "7")
955         ->EndWrap();
956     rdbPredicates.BeginWrap()
957         ->BeginWrap()
958         ->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->EqualTo(PhotoColumn::PHOTO_POSITION, "3")
959         ->EndWrap()->Or()->BeginWrap()
960         ->EqualTo(PhotoColumn::PHOTO_POSITION, "2")->And()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, "0")
961         ->EndWrap()->EndWrap();
962     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
963     if (opts.store == nullptr) {
964         MEDIA_ERR_LOG("opts.store is nullptr");
965         return false;
966     }
967     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
968     if (!CheckResultSetCount(resultSet, err)) {
969         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
970         if (err == E_EMPTY_VALUES_BUCKET) {
971             return true;
972         }
973         return false;
974     }
975 
976     err = resultSet->GoToFirstRow();
977     if (err != E_OK) {
978         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
979         return false;
980     }
981 
982     ThumbnailData data;
983     do {
984         ParseQueryResult(resultSet, data, err, column);
985         if (!data.path.empty()) {
986             infos.push_back(data);
987         }
988     } while (resultSet->GoToNextRow() == E_OK);
989     return true;
990 }
991 
QueryNewThumbnailCount(ThumbRdbOpt & opts,const int64_t & time,int & count,int & err)992 bool ThumbnailUtils::QueryNewThumbnailCount(ThumbRdbOpt &opts, const int64_t &time, int &count,
993     int &err)
994 {
995     vector<string> column = {
996         MEDIA_DATA_DB_ID,
997     };
998     RdbPredicates rdbPredicates(opts.table);
999     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
1000         rdbPredicates.GreaterThan(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
1001     }
1002     if (opts.table == MEDIALIBRARY_TABLE) {
1003         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
1004     } else {
1005         rdbPredicates.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
1006     }
1007     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
1008     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
1009     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
1010 
1011     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
1012     if (opts.store == nullptr) {
1013         MEDIA_ERR_LOG("opts.store is nullptr");
1014         return false;
1015     }
1016     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
1017     if (resultSet == nullptr) {
1018         MEDIA_ERR_LOG("ResultSet is nullptr");
1019         return false;
1020     }
1021     int rowCount = 0;
1022     err = resultSet->GetRowCount(rowCount);
1023     resultSet.reset();
1024     if (err != E_OK) {
1025         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
1026         return false;
1027     }
1028     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
1029     if (rowCount <= 0) {
1030         MEDIA_INFO_LOG("No match! %{public}s", rdbPredicates.ToString().c_str());
1031         rowCount = 0;
1032     }
1033 
1034     count = rowCount;
1035     return true;
1036 }
1037 
UpdateLcdInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1038 bool ThumbnailUtils::UpdateLcdInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1039 {
1040     ValuesBucket values;
1041     int changedRows;
1042 
1043     MediaLibraryTracer tracer;
1044     tracer.Start("UpdateLcdInfo opts.store->Update");
1045     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, MediaFileUtils::UTCTimeMilliSeconds());
1046     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(LcdReady::GENERATE_LCD_COMPLETED));
1047 
1048     Size lcdSize;
1049     if (GetLocalThumbSize(data, ThumbnailType::LCD, lcdSize)) {
1050         SetThumbnailSizeValue(values, lcdSize, PhotoColumn::PHOTO_LCD_SIZE);
1051     }
1052     if (opts.store == nullptr) {
1053         MEDIA_ERR_LOG("opts.store is nullptr");
1054         return false;
1055     }
1056     err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1057         vector<string> { opts.row });
1058     if (err != NativeRdb::E_OK) {
1059         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1060         return false;
1061     }
1062     return true;
1063 }
1064 
UpdateVisitTime(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1065 bool ThumbnailUtils::UpdateVisitTime(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1066 {
1067 #ifdef DISTRIBUTED
1068     if (!opts.networkId.empty()) {
1069         return DoUpdateRemoteThumbnail(opts, data, err);
1070     }
1071 #endif
1072 
1073     ValuesBucket values;
1074     int changedRows;
1075     int64_t timeNow = UTCTimeMilliSeconds();
1076     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, timeNow);
1077     if (opts.store == nullptr) {
1078         MEDIA_ERR_LOG("opts.store is nullptr");
1079         return false;
1080     }
1081     err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1082         vector<string> { opts.row });
1083     if (err != NativeRdb::E_OK) {
1084         MEDIA_ERR_LOG("UpdateVisitTime rdbStore Update failed! %{public}d", err);
1085         return false;
1086     }
1087     return true;
1088 }
1089 
UpdateLcdReadyStatus(ThumbRdbOpt & opts,ThumbnailData & data,int & err,LcdReady status)1090 bool ThumbnailUtils::UpdateLcdReadyStatus(ThumbRdbOpt &opts, ThumbnailData &data, int &err, LcdReady status)
1091 {
1092     ValuesBucket values;
1093     int changedRows;
1094     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(status));
1095     if (opts.store == nullptr) {
1096         MEDIA_ERR_LOG("opts.store is nullptr");
1097         return false;
1098     }
1099     err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1100         vector<string> { opts.row });
1101     if (err != NativeRdb::E_OK) {
1102         MEDIA_ERR_LOG("UpdateLcdReadyStatus rdbStore Update failed! %{public}d", err);
1103         return false;
1104     }
1105     return true;
1106 }
1107 
1108 #ifdef DISTRIBUTED
QueryDeviceThumbnailRecords(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)1109 bool ThumbnailUtils::QueryDeviceThumbnailRecords(ThumbRdbOpt &opts, vector<ThumbnailData> &infos,
1110     int &err)
1111 {
1112     vector<string> column = {
1113         REMOTE_THUMBNAIL_DB_FILE_ID,
1114         MEDIA_DATA_DB_THUMBNAIL,
1115         MEDIA_DATA_DB_LCD
1116     };
1117     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
1118     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
1119     if (opts.store == nullptr) {
1120         MEDIA_ERR_LOG("opts.store is nullptr");
1121         return false;
1122     }
1123     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
1124     if (!CheckResultSetCount(resultSet, err)) {
1125         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
1126         return false;
1127     }
1128 
1129     err = resultSet->GoToFirstRow();
1130     if (err != E_OK) {
1131         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
1132         return false;
1133     }
1134 
1135     ThumbnailData data;
1136     do {
1137         ParseQueryResult(resultSet, data, err, column);
1138         infos.push_back(data);
1139     } while (resultSet->GoToNextRow() == E_OK);
1140     return true;
1141 }
1142 
GetUdidByNetworkId(ThumbRdbOpt & opts,const string & networkId,string & outUdid,int & err)1143 bool ThumbnailUtils::GetUdidByNetworkId(ThumbRdbOpt &opts, const string &networkId,
1144     string &outUdid, int &err)
1145 {
1146     vector<string> column = {
1147         DEVICE_DB_ID,
1148         DEVICE_DB_UDID
1149     };
1150     RdbPredicates rdbPredicates(DEVICE_TABLE);
1151     rdbPredicates.EqualTo(DEVICE_DB_NETWORK_ID, networkId);
1152     if (opts.store == nullptr) {
1153         MEDIA_ERR_LOG("opts.store is nullptr");
1154         return false;
1155     }
1156     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
1157     if (!CheckResultSetCount(resultSet, err)) {
1158         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
1159         return false;
1160     }
1161 
1162     err = resultSet->GoToFirstRow();
1163     if (err != E_OK) {
1164         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
1165         return false;
1166     }
1167     int index;
1168     err = resultSet->GetColumnIndex(DEVICE_DB_UDID, index);
1169     if (err == NativeRdb::E_OK) {
1170         ParseStringResult(resultSet, index, outUdid, err);
1171     } else {
1172         MEDIA_ERR_LOG("Get column index error %{public}d", err);
1173     }
1174     return true;
1175 }
1176 
QueryRemoteThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1177 bool ThumbnailUtils::QueryRemoteThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1178 {
1179     if (data.udid.empty() && !GetUdidByNetworkId(opts, opts.networkId, data.udid, err)) {
1180         MEDIA_ERR_LOG("GetUdidByNetworkId failed! %{public}d", err);
1181         return false;
1182     }
1183 
1184     vector<string> column = {
1185         REMOTE_THUMBNAIL_DB_ID,
1186         MEDIA_DATA_DB_THUMBNAIL,
1187         MEDIA_DATA_DB_LCD
1188     };
1189     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
1190     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, data.id);
1191     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, data.udid);
1192     if (opts.store == nullptr) {
1193         MEDIA_ERR_LOG("opts.store is nullptr");
1194         return false;
1195     }
1196     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
1197     if (!CheckResultSetCount(resultSet, err)) {
1198         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
1199         return false;
1200     }
1201 
1202     err = resultSet->GoToFirstRow();
1203     if (err != E_OK) {
1204         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
1205         return false;
1206     }
1207 
1208     int index;
1209     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_LCD, index);
1210     if (err == NativeRdb::E_OK) {
1211         ParseStringResult(resultSet, index, data.lcdKey, err);
1212     }
1213 
1214     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_THUMBNAIL, index);
1215     if (err == NativeRdb::E_OK) {
1216         ParseStringResult(resultSet, index, data.thumbnailKey, err);
1217     }
1218     return true;
1219 }
1220 
IsKeyNotSame(const string & newKey,const string & oldKey)1221 static inline bool IsKeyNotSame(const string &newKey, const string &oldKey)
1222 {
1223     return !newKey.empty() && !oldKey.empty() && (newKey != oldKey);
1224 }
1225 
DoUpdateRemoteThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1226 bool ThumbnailUtils::DoUpdateRemoteThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1227 {
1228     if (opts.networkId.empty()) {
1229         return false;
1230     }
1231     if (data.thumbnailKey.empty() && data.lcdKey.empty()) {
1232         return false;
1233     }
1234     ThumbnailData tmpData = data;
1235     auto isGot = ThumbnailUtils::QueryRemoteThumbnail(opts, tmpData, err);
1236     if (isGot) {
1237         if (IsKeyNotSame(data.thumbnailKey, tmpData.thumbnailKey)) {
1238             if (!RemoveDataFromKv(opts.kvStore, tmpData.thumbnailKey)) {
1239                 return false;
1240             }
1241         }
1242         if (IsKeyNotSame(data.lcdKey, tmpData.lcdKey)) {
1243             if (!RemoveDataFromKv(opts.kvStore, tmpData.lcdKey)) {
1244                 return false;
1245             }
1246         }
1247     }
1248 
1249     data.udid = tmpData.udid;
1250     if (isGot) {
1251         return UpdateRemoteThumbnailInfo(opts, data, err);
1252     } else {
1253         return InsertRemoteThumbnailInfo(opts, data, err);
1254     }
1255 }
1256 
UpdateRemoteThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1257 bool ThumbnailUtils::UpdateRemoteThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1258 {
1259     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
1260     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, data.id);
1261     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, data.udid);
1262 
1263     ValuesBucket values;
1264     if (!data.thumbnailKey.empty()) {
1265         values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
1266     }
1267 
1268     if (!data.lcdKey.empty()) {
1269         values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
1270     }
1271 
1272     int changedRows;
1273     if (opts.store == nullptr) {
1274         MEDIA_ERR_LOG("opts.store is nullptr");
1275         return false;
1276     }
1277     err = opts.store->Update(changedRows, values, rdbPredicates);
1278     if (err != NativeRdb::E_OK) {
1279         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1280         return false;
1281     }
1282 
1283     return true;
1284 }
1285 
InsertRemoteThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1286 bool ThumbnailUtils::InsertRemoteThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1287 {
1288     ValuesBucket values;
1289     values.PutInt(REMOTE_THUMBNAIL_DB_FILE_ID, stoi(data.id));
1290     values.PutString(REMOTE_THUMBNAIL_DB_UDID, data.udid);
1291     if (!data.thumbnailKey.empty()) {
1292         values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
1293     }
1294 
1295     if (!data.lcdKey.empty()) {
1296         values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
1297     }
1298 
1299     int64_t outRowId = -1;
1300     if (opts.store == nullptr) {
1301         MEDIA_ERR_LOG("opts.store is nullptr");
1302         return false;
1303     }
1304     err = opts.store->Insert(outRowId, REMOTE_THUMBNAIL_TABLE, values);
1305     if (err != NativeRdb::E_OK) {
1306         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1307         return false;
1308     }
1309     return true;
1310 }
1311 #endif
1312 
CleanThumbnailInfo(ThumbRdbOpt & opts,bool withThumb,bool withLcd)1313 bool ThumbnailUtils::CleanThumbnailInfo(ThumbRdbOpt &opts, bool withThumb, bool withLcd)
1314 {
1315     ValuesBucket values;
1316     if (withThumb) {
1317         values.PutNull(MEDIA_DATA_DB_THUMBNAIL);
1318     }
1319     if (withLcd) {
1320         values.PutInt(MEDIA_DATA_DB_DIRTY, static_cast<int32_t>(DirtyType::TYPE_SYNCED));
1321         if (opts.table == MEDIALIBRARY_TABLE) {
1322             values.PutNull(MEDIA_DATA_DB_LCD);
1323         }
1324         if (opts.table == PhotoColumn::PHOTOS_TABLE) {
1325             values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, 0);
1326         }
1327     }
1328     int changedRows;
1329     if (opts.store == nullptr) {
1330         MEDIA_ERR_LOG("opts.store is nullptr");
1331         return false;
1332     }
1333     auto err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1334         vector<string> { opts.row });
1335     if (err != NativeRdb::E_OK) {
1336         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1337         return false;
1338     }
1339     return true;
1340 }
1341 
1342 #ifdef DISTRIBUTED
CleanDistributeLcdInfo(ThumbRdbOpt & opts)1343 bool ThumbnailUtils::CleanDistributeLcdInfo(ThumbRdbOpt &opts)
1344 {
1345     string udid;
1346     int err;
1347     if (!GetUdidByNetworkId(opts, opts.networkId, udid, err)) {
1348         MEDIA_ERR_LOG("GetUdidByNetworkId failed! %{public}d", err);
1349         return false;
1350     }
1351 
1352     ValuesBucket values;
1353     values.PutNull(MEDIA_DATA_DB_LCD);
1354     int changedRows;
1355     vector<string> whereArgs = { udid, opts.row };
1356     string deleteCondition = REMOTE_THUMBNAIL_DB_UDID + " = ? AND " +
1357         REMOTE_THUMBNAIL_DB_FILE_ID + " = ?";
1358     if (opts.store == nullptr) {
1359         MEDIA_ERR_LOG("opts.store is nullptr");
1360         return false;
1361     }
1362     auto ret = opts.store->Update(changedRows, REMOTE_THUMBNAIL_TABLE, values, deleteCondition, whereArgs);
1363     if (ret != NativeRdb::E_OK) {
1364         MEDIA_ERR_LOG("RdbStore Delete failed! %{public}d", ret);
1365         return false;
1366     }
1367     return true;
1368 }
1369 
DeleteDistributeThumbnailInfo(ThumbRdbOpt & opts)1370 bool ThumbnailUtils::DeleteDistributeThumbnailInfo(ThumbRdbOpt &opts)
1371 {
1372     int changedRows;
1373     vector<string> whereArgs = { opts.udid, opts.row };
1374     string deleteCondition = REMOTE_THUMBNAIL_DB_UDID + " = ? AND " +
1375         REMOTE_THUMBNAIL_DB_FILE_ID + " = ?";
1376     if (opts.store == nullptr) {
1377         MEDIA_ERR_LOG("opts.store is nullptr");
1378         return false;
1379     }
1380     auto err = opts.store->Delete(changedRows, REMOTE_THUMBNAIL_TABLE, deleteCondition, whereArgs);
1381     if (err != NativeRdb::E_OK) {
1382         MEDIA_ERR_LOG("RdbStore Delete failed! %{public}d", err);
1383         return false;
1384     }
1385     return true;
1386 }
1387 #endif
1388 
PostProcPixelMapSource(ThumbnailData & data)1389 void PostProcPixelMapSource(ThumbnailData &data)
1390 {
1391     auto pixelMap = data.source.GetPixelMap();
1392     if (pixelMap == nullptr) {
1393         return;
1394     }
1395     pixelMap->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
1396     if (data.orientation != 0) {
1397         if (data.isLocalFile) {
1398             Media::InitializationOptions opts;
1399             auto copySourcePtr = PixelMap::Create(*pixelMap, opts);
1400             std::shared_ptr<PixelMap> copySource = std::move(copySourcePtr);
1401             data.source.SetPixelMapEx(copySource);
1402         }
1403         pixelMap->rotate(static_cast<float>(data.orientation));
1404     }
1405 
1406     // PixelMap has been rotated, fix the exif orientation to zero degree.
1407     pixelMap->ModifyImageProperty(PHOTO_DATA_IMAGE_ORIENTATION, DEFAULT_EXIF_ORIENTATION);
1408 }
1409 
CopyPictureSource(std::shared_ptr<Picture> & picture,std::shared_ptr<Picture> & copySource)1410 bool ThumbnailUtils::CopyPictureSource(std::shared_ptr<Picture> &picture, std::shared_ptr<Picture> &copySource)
1411 {
1412     auto pixelMap = picture->GetMainPixel();
1413     auto gainMap = picture->GetGainmapPixelMap();
1414     if (pixelMap == nullptr || gainMap == nullptr) {
1415         return false;
1416     }
1417     Media::InitializationOptions pixelMapOpts = {
1418         .size = {pixelMap->GetWidth(), pixelMap->GetHeight()},
1419         .pixelFormat = pixelMap->GetPixelFormat(),
1420         .alphaType = pixelMap->GetAlphaType()
1421     };
1422     auto copyPixelMapPtr = PixelMap::Create(*pixelMap, pixelMapOpts);
1423     std::shared_ptr<PixelMap> copyPixelMap = std::move(copyPixelMapPtr);
1424     if (copyPixelMap == nullptr) {
1425         return false;
1426     }
1427 
1428     Media::InitializationOptions gainMapOpts = {
1429         .size = {gainMap->GetWidth(), gainMap->GetHeight()},
1430         .pixelFormat = gainMap->GetPixelFormat(),
1431         .alphaType = gainMap->GetAlphaType()
1432     };
1433     auto copyGainMapPtr = PixelMap::Create(*gainMap, gainMapOpts);
1434     std::shared_ptr<PixelMap> copyGainMap = std::move(copyGainMapPtr);
1435     if (copyGainMap == nullptr) {
1436         return false;
1437     }
1438     Size copyGainMapSize = {copyGainMap->GetWidth(), copyGainMap->GetHeight()};
1439     auto auxiliaryPicturePtr = AuxiliaryPicture::Create(copyGainMap, AuxiliaryPictureType::GAINMAP, copyGainMapSize);
1440     std::shared_ptr<AuxiliaryPicture> auxiliaryPicture = std::move(auxiliaryPicturePtr);
1441     if (auxiliaryPicture == nullptr) {
1442         return false;
1443     }
1444     auto copySourcePtr = Picture::Create(copyPixelMap);
1445     copySource = std::move(copySourcePtr);
1446     copySource->SetAuxiliaryPicture(auxiliaryPicture);
1447     return true;
1448 }
1449 
PostProcPictureSource(ThumbnailData & data)1450 void PostProcPictureSource(ThumbnailData &data)
1451 {
1452     auto picture = data.source.GetPicture();
1453     if (picture == nullptr) {
1454         return;
1455     }
1456     auto pixelMap = picture->GetMainPixel();
1457     auto gainMap = picture->GetGainmapPixelMap();
1458     if (pixelMap == nullptr || gainMap == nullptr) {
1459         return;
1460     }
1461     if (data.orientation != 0) {
1462         if (data.isLocalFile) {
1463             std::shared_ptr<Picture> copySource;
1464             ThumbnailUtils::CopyPictureSource(picture, copySource);
1465             data.source.SetPictureEx(copySource);
1466         }
1467         pixelMap->rotate(static_cast<float>(data.orientation));
1468         gainMap->rotate(static_cast<float>(data.orientation));
1469     }
1470 }
1471 
LoadSourceImage(ThumbnailData & data)1472 bool ThumbnailUtils::LoadSourceImage(ThumbnailData &data)
1473 {
1474     if (!data.source.IsEmptySource()) {
1475         return true;
1476     }
1477     MediaLibraryTracer tracer;
1478     tracer.Start("LoadSourceImage");
1479     if (data.mediaType == -1) {
1480         auto extension = MediaFileUtils::GetExtensionFromPath(data.path);
1481         auto mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension);
1482         data.mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1483     }
1484 
1485     bool ret = false;
1486     Size desiredSize;
1487     if (data.mediaType == MEDIA_TYPE_AUDIO) {
1488         ret = LoadAudioFile(data, desiredSize);
1489     } else {
1490         ret = LoadImageFile(data, desiredSize);
1491     }
1492     if (!ret || (data.source.IsEmptySource())) {
1493         return false;
1494     }
1495     tracer.Finish();
1496 
1497     auto pixelMap = data.source.GetPixelMap();
1498     if (data.loaderOpts.decodeInThumbSize && !CenterScaleEx(pixelMap, desiredSize, data.path)) {
1499         MEDIA_ERR_LOG("thumbnail center crop failed [%{private}s]", data.id.c_str());
1500         return false;
1501     }
1502 
1503     if (data.source.HasPictureSource()) {
1504         PostProcPictureSource(data);
1505     } else {
1506         PostProcPixelMapSource(data);
1507     }
1508     return true;
1509 }
1510 
ScaleFastThumb(ThumbnailData & data,const Size & size)1511 bool ThumbnailUtils::ScaleFastThumb(ThumbnailData &data, const Size &size)
1512 {
1513     MediaLibraryTracer tracer;
1514     tracer.Start("ScaleFastThumb");
1515 
1516     auto pixelMap = data.source.GetPixelMap();
1517     if (!CenterScaleEx(pixelMap, size, data.path)) {
1518         MEDIA_ERR_LOG("Fast thumb center crop failed [%{private}s]", data.id.c_str());
1519         return false;
1520     }
1521     return true;
1522 }
1523 
SaveFile(const string & fileName,uint8_t * output,int writeSize)1524 static int SaveFile(const string &fileName, uint8_t *output, int writeSize)
1525 {
1526     string tempFileName = fileName + ".tmp";
1527     const mode_t fileMode = 0644;
1528     mode_t mask = umask(0);
1529     UniqueFd fd(open(tempFileName.c_str(), O_WRONLY | O_CREAT | O_TRUNC, fileMode));
1530     umask(mask);
1531     if (fd.Get() < 0) {
1532         if (errno == EEXIST) {
1533             UniqueFd fd(open(tempFileName.c_str(), O_WRONLY | O_TRUNC, fileMode));
1534         }
1535         if (fd.Get() < 0) {
1536             int err = errno;
1537             std::string fileParentPath = MediaFileUtils::GetParentPath(tempFileName);
1538             MEDIA_ERR_LOG("save failed! status %{public}d, filePath: %{public}s exists: %{public}d, parent path "
1539                 "exists: %{public}d", err, DfxUtils::GetSafePath(tempFileName).c_str(), MediaFileUtils::IsFileExists(
1540                     tempFileName), MediaFileUtils::IsFileExists(fileParentPath));
1541             if (err == EACCES) {
1542                 MediaFileUtils::PrintStatInformation(fileParentPath);
1543             }
1544             return -err;
1545         }
1546     }
1547     int ret = write(fd.Get(), output, writeSize);
1548     if (ret < 0) {
1549         MEDIA_ERR_LOG("write failed errno %{public}d", errno);
1550         return -errno;
1551     }
1552     int32_t errCode = fsync(fd.Get());
1553     if (errCode < 0) {
1554         MEDIA_ERR_LOG("fsync failed errno %{public}d", errno);
1555         return -errno;
1556     }
1557     close(fd.Release());
1558 
1559     if (MediaFileUtils::IsFileExists(fileName)) {
1560         MEDIA_INFO_LOG("file: %{public}s exists and needs to be deleted", DfxUtils::GetSafePath(fileName).c_str());
1561         if (!MediaFileUtils::DeleteFile(fileName)) {
1562             MEDIA_ERR_LOG("delete file: %{public}s failed", DfxUtils::GetSafePath(fileName).c_str());
1563             return -errno;
1564         }
1565     }
1566     errCode = MediaFileUtils::ModifyAsset(tempFileName, fileName);
1567     if (errCode != E_OK) {
1568         int32_t lastErrno = errno;
1569         if (!MediaFileUtils::DeleteFile(tempFileName)) {
1570             MEDIA_WARN_LOG("Delete tmp thumb error: %{public}d, name: %{public}s",
1571                 errno, DfxUtils::GetSafePath(tempFileName).c_str());
1572         }
1573         if (errCode == E_FILE_EXIST || (errCode == E_FILE_OPER_FAIL && lastErrno == EEXIST)) {
1574             return E_OK;
1575         }
1576         return errCode;
1577     }
1578     return ret;
1579 }
1580 
SaveFileCreateDir(const string & path,const string & suffix,string & fileName)1581 int ThumbnailUtils::SaveFileCreateDir(const string &path, const string &suffix, string &fileName)
1582 {
1583     fileName = GetThumbnailPath(path, suffix);
1584     string dir = MediaFileUtils::GetParentPath(fileName);
1585     if (!MediaFileUtils::CreateDirectory(dir)) {
1586         MEDIA_ERR_LOG("Fail to create directory, fileName: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
1587         return -errno;
1588     }
1589     return E_OK;
1590 }
1591 
ToSaveFile(ThumbnailData & data,const string & fileName,uint8_t * output,const int & writeSize)1592 int ThumbnailUtils::ToSaveFile(ThumbnailData &data, const string &fileName, uint8_t *output, const int &writeSize)
1593 {
1594     int ret = SaveFile(fileName, output, writeSize);
1595     if (ret < 0) {
1596         MEDIA_ERR_LOG("Fail to save File, err: %{public}d", ret);
1597         return ret;
1598     } else if (ret != writeSize) {
1599         MEDIA_ERR_LOG("Fail to save File, insufficient space left.");
1600         return E_NO_SPACE;
1601     }
1602     return E_OK;
1603 }
1604 
TrySaveFile(ThumbnailData & data,ThumbnailType type)1605 int ThumbnailUtils::TrySaveFile(ThumbnailData &data, ThumbnailType type)
1606 {
1607     string suffix;
1608     uint8_t *output;
1609     uint32_t writeSize;
1610     switch (type) {
1611         case ThumbnailType::THUMB:
1612             suffix = THUMBNAIL_THUMB_SUFFIX;
1613             output = data.thumbnail.data();
1614             writeSize = data.thumbnail.size();
1615             break;
1616         case ThumbnailType::THUMB_ASTC:
1617             suffix = THUMBNAIL_THUMBASTC_SUFFIX;
1618             output = data.thumbAstc.data();
1619             writeSize = data.thumbAstc.size();
1620             break;
1621         case ThumbnailType::LCD:
1622             suffix = THUMBNAIL_LCD_SUFFIX;
1623             output = data.lcd.data();
1624             writeSize = data.lcd.size();
1625             break;
1626         case ThumbnailType::MTH_ASTC:
1627             output = data.monthAstc.data();
1628             writeSize = data.monthAstc.size();
1629             break;
1630         case ThumbnailType::YEAR_ASTC:
1631             output = data.yearAstc.data();
1632             writeSize = data.yearAstc.size();
1633             break;
1634         case ThumbnailType::LCD_EX:
1635             suffix = THUMBNAIL_LCD_EX_SUFFIX;
1636             output = data.lcd.data();
1637             writeSize = data.lcd.size();
1638             break;
1639         case ThumbnailType::THUMB_EX:
1640             suffix = THUMBNAIL_THUMB_EX_SUFFIX;
1641             output = data.thumbnail.data();
1642             writeSize = data.thumbnail.size();
1643             break;
1644         default:
1645             return E_INVALID_ARGUMENTS;
1646     }
1647     if (writeSize <= 0) {
1648         return E_THUMBNAIL_LOCAL_CREATE_FAIL;
1649     }
1650     if (type == ThumbnailType::MTH_ASTC || type == ThumbnailType::YEAR_ASTC) {
1651         return SaveAstcDataToKvStore(data, type);
1652     }
1653     return SaveThumbDataToLocalDir(data, suffix, output, writeSize);
1654 }
1655 
SaveThumbDataToLocalDir(ThumbnailData & data,const std::string & suffix,uint8_t * output,const int writeSize)1656 int ThumbnailUtils::SaveThumbDataToLocalDir(ThumbnailData &data, const std::string &suffix,
1657     uint8_t *output, const int writeSize)
1658 {
1659     string fileName;
1660     int ret = SaveFileCreateDir(data.path, suffix, fileName);
1661     if (ret != E_OK) {
1662         MEDIA_ERR_LOG("SaveThumbDataToLocalDir create dir path %{public}s err %{public}d",
1663             DfxUtils::GetSafePath(data.path).c_str(), ret);
1664         return ret;
1665     }
1666     ret = ToSaveFile(data, fileName, output, writeSize);
1667     if (ret < 0) {
1668         MEDIA_ERR_LOG("SaveThumbDataToLocalDir ToSaveFile path %{public}s err %{public}d",
1669             DfxUtils::GetSafePath(data.path).c_str(), ret);
1670         return ret;
1671     }
1672     return E_OK;
1673 }
1674 
SetSource(shared_ptr<AVMetadataHelper> avMetadataHelper,const string & path)1675 int32_t ThumbnailUtils::SetSource(shared_ptr<AVMetadataHelper> avMetadataHelper, const string &path)
1676 {
1677     if (avMetadataHelper == nullptr) {
1678         MEDIA_ERR_LOG("avMetadataHelper == nullptr");
1679         return E_ERR;
1680     }
1681     MEDIA_DEBUG_LOG("path = %{public}s", DfxUtils::GetSafePath(path).c_str());
1682 
1683     string absFilePath;
1684     if (!PathToRealPath(path, absFilePath)) {
1685         MEDIA_ERR_LOG("Failed to open a nullptr path, errno=%{public}d, path:%{public}s",
1686             errno, DfxUtils::GetSafePath(path).c_str());
1687         return E_ERR;
1688     }
1689 
1690     int32_t fd = open(absFilePath.c_str(), O_RDONLY);
1691     if (fd < 0) {
1692         MEDIA_ERR_LOG("Open file failed, err %{public}d, file: %{public}s exists: %{public}d",
1693             errno, DfxUtils::GetSafePath(absFilePath).c_str(), MediaFileUtils::IsFileExists(absFilePath));
1694         return E_ERR;
1695     }
1696     struct stat64 st;
1697     if (fstat64(fd, &st) != 0) {
1698         MEDIA_ERR_LOG("Get file state failed, err %{public}d", errno);
1699         (void)close(fd);
1700         return E_ERR;
1701     }
1702     int64_t length = static_cast<int64_t>(st.st_size);
1703     int32_t ret = avMetadataHelper->SetSource(fd, 0, length, AV_META_USAGE_PIXEL_MAP);
1704     if (ret != 0) {
1705         DfxManager::GetInstance()->HandleThumbnailError(absFilePath, DfxType::AV_SET_SOURCE, ret);
1706         (void)close(fd);
1707         return E_ERR;
1708     }
1709     (void)close(fd);
1710     return E_SUCCESS;
1711 }
1712 
ResizeImage(const vector<uint8_t> & data,const Size & size,unique_ptr<PixelMap> & pixelMap)1713 bool ThumbnailUtils::ResizeImage(const vector<uint8_t> &data, const Size &size, unique_ptr<PixelMap> &pixelMap)
1714 {
1715     MediaLibraryTracer tracer;
1716     tracer.Start("ResizeImage");
1717     if (data.size() == 0) {
1718         MEDIA_ERR_LOG("Data is empty");
1719         return false;
1720     }
1721 
1722     tracer.Start("ImageSource::CreateImageSource");
1723     uint32_t err = E_OK;
1724     SourceOptions opts;
1725     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(data.data(),
1726         data.size(), opts, err);
1727     if (imageSource == nullptr) {
1728         MEDIA_ERR_LOG("imageSource is nullptr");
1729         return false;
1730     }
1731     if (err != E_OK) {
1732         MEDIA_ERR_LOG("Failed to create image source %{public}d", err);
1733         return false;
1734     }
1735     tracer.Finish();
1736 
1737     tracer.Start("imageSource->CreatePixelMap");
1738     DecodeOptions decodeOpts;
1739     decodeOpts.desiredSize.width = size.width;
1740     decodeOpts.desiredSize.height = size.height;
1741     pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
1742     if (err != E_SUCCESS) {
1743         MEDIA_ERR_LOG("Failed to create pixelmap %{public}d", err);
1744         return false;
1745     }
1746 
1747     return true;
1748 }
1749 
1750 // notice: return value is whether thumb/lcd is deleted
DeleteOriginImage(ThumbRdbOpt & opts)1751 bool ThumbnailUtils::DeleteOriginImage(ThumbRdbOpt &opts)
1752 {
1753     ThumbnailData tmpData;
1754     tmpData.path = opts.path;
1755     bool isDelete = false;
1756     if (opts.path.empty()) {
1757         int err = 0;
1758         auto rdbSet = QueryThumbnailInfo(opts, tmpData, err);
1759         if (rdbSet == nullptr) {
1760             MEDIA_ERR_LOG("QueryThumbnailInfo Faild [ %{public}d ]", err);
1761             return isDelete;
1762         }
1763     }
1764     ValuesBucket values;
1765     int changedRows;
1766     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, 0);
1767     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, 0);
1768     int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1769         vector<string> { opts.row });
1770     if (err != NativeRdb::E_OK) {
1771         MEDIA_ERR_LOG("RdbStore Update Failed Before Delete Thumbnail! %{public}d", err);
1772     }
1773     MEDIA_INFO_LOG("Start DeleteOriginImage, id: %{public}s, path: %{public}s",
1774         opts.row.c_str(), DfxUtils::GetSafePath(tmpData.path).c_str());
1775     if (!opts.dateTaken.empty() && DeleteAstcDataFromKvStore(opts, ThumbnailType::MTH_ASTC)) {
1776         isDelete = true;
1777     }
1778     if (!opts.dateTaken.empty() && DeleteAstcDataFromKvStore(opts, ThumbnailType::YEAR_ASTC)) {
1779         isDelete = true;
1780     }
1781     if (DeleteThumbFile(tmpData, ThumbnailType::THUMB)) {
1782         isDelete = true;
1783     }
1784     if (ThumbnailUtils::IsSupportGenAstc() && DeleteThumbFile(tmpData, ThumbnailType::THUMB_ASTC)) {
1785         isDelete = true;
1786     }
1787     if (DeleteThumbFile(tmpData, ThumbnailType::LCD)) {
1788         isDelete = true;
1789     }
1790     if (DeleteThumbExDir(tmpData)) {
1791         isDelete = true;
1792     }
1793     string fileName = GetThumbnailPath(tmpData.path, "");
1794     return isDelete;
1795 }
1796 
DoDeleteMonthAndYearAstc(ThumbRdbOpt & opts)1797 bool ThumbnailUtils::DoDeleteMonthAndYearAstc(ThumbRdbOpt &opts)
1798 {
1799     MEDIA_INFO_LOG("Start DoDeleteMonthAndYearAstc, id: %{public}s", opts.row.c_str());
1800     bool isDeleteAstcSuccess = true;
1801     if (!DeleteAstcDataFromKvStore(opts, ThumbnailType::MTH_ASTC)) {
1802         isDeleteAstcSuccess = false;
1803     }
1804     if (!DeleteAstcDataFromKvStore(opts, ThumbnailType::YEAR_ASTC)) {
1805         isDeleteAstcSuccess = false;
1806     }
1807     return isDeleteAstcSuccess;
1808 }
1809 
DoUpdateAstcDateTaken(ThumbRdbOpt & opts,ThumbnailData & data)1810 bool ThumbnailUtils::DoUpdateAstcDateTaken(ThumbRdbOpt &opts, ThumbnailData &data)
1811 {
1812     MEDIA_INFO_LOG("Start DoUpdateAstcDateTaken, id: %{public}s", opts.row.c_str());
1813     return UpdateAstcDateTakenFromKvStore(opts, data);
1814 }
1815 
1816 #ifdef DISTRIBUTED
IsImageExist(const string & key,const string & networkId,const shared_ptr<SingleKvStore> & kvStore)1817 bool ThumbnailUtils::IsImageExist(const string &key, const string &networkId, const shared_ptr<SingleKvStore> &kvStore)
1818 {
1819     if (key.empty()) {
1820         return false;
1821     }
1822 
1823     if (kvStore == nullptr) {
1824         MEDIA_ERR_LOG("KvStore is not init");
1825         return false;
1826     }
1827 
1828     bool ret = false;
1829     DataQuery query;
1830     query.InKeys({key});
1831     int count = 0;
1832     auto status = kvStore->GetCount(query, count);
1833     if (status == Status::SUCCESS && count > 0) {
1834         ret = true;
1835     }
1836 
1837     if (!ret) {
1838         if (!networkId.empty()) {
1839             MediaLibraryTracer tracer;
1840             tracer.Start("SyncPullKvstore");
1841             vector<string> keys = { key };
1842             auto syncStatus = MediaLibrarySyncOperation::SyncPullKvstore(kvStore, keys, networkId);
1843             if (syncStatus == DistributedKv::Status::SUCCESS) {
1844                 MEDIA_DEBUG_LOG("SyncPullKvstore SUCCESS");
1845                 return true;
1846             } else {
1847                 MEDIA_ERR_LOG("SyncPullKvstore failed! ret %{public}d", syncStatus);
1848                 return false;
1849             }
1850         }
1851     }
1852     return ret;
1853 }
1854 #endif
1855 
UTCTimeMilliSeconds()1856 int64_t ThumbnailUtils::UTCTimeMilliSeconds()
1857 {
1858     struct timespec t;
1859     constexpr int64_t SEC_TO_MSEC = 1e3;
1860     constexpr int64_t MSEC_TO_NSEC = 1e6;
1861     clock_gettime(CLOCK_REALTIME, &t);
1862     return t.tv_sec * SEC_TO_MSEC + t.tv_nsec / MSEC_TO_NSEC;
1863 }
1864 
CheckResultSetCount(const shared_ptr<ResultSet> & resultSet,int & err)1865 bool ThumbnailUtils::CheckResultSetCount(const shared_ptr<ResultSet> &resultSet, int &err)
1866 {
1867     if (resultSet == nullptr) {
1868         MEDIA_ERR_LOG("resultSet is nullptr!");
1869         return false;
1870     }
1871     int rowCount = 0;
1872     err = resultSet->GetRowCount(rowCount);
1873     if (err != E_OK || rowCount < 0) {
1874         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
1875         return false;
1876     } else if (rowCount == 0) {
1877         MEDIA_ERR_LOG("CheckCount No match!");
1878         err = E_EMPTY_VALUES_BUCKET;
1879         return false;
1880     }
1881     return true;
1882 }
1883 
ParseStringResult(const shared_ptr<ResultSet> & resultSet,int index,string & data,int & err)1884 void ThumbnailUtils::ParseStringResult(const shared_ptr<ResultSet> &resultSet, int index, string &data, int &err)
1885 {
1886     bool isNull = true;
1887     err = resultSet->IsColumnNull(index, isNull);
1888     if (err != E_OK) {
1889         MEDIA_ERR_LOG("Failed to check column %{public}d null %{public}d", index, err);
1890     }
1891 
1892     if (!isNull) {
1893         err = resultSet->GetString(index, data);
1894         if (err != E_OK) {
1895             MEDIA_ERR_LOG("Failed to get column %{public}d string %{public}d", index, err);
1896         }
1897     }
1898 }
1899 
ParseQueryResult(const shared_ptr<ResultSet> & resultSet,ThumbnailData & data,int & err,const std::vector<std::string> & column)1900 void ThumbnailUtils::ParseQueryResult(const shared_ptr<ResultSet> &resultSet, ThumbnailData &data,
1901     int &err, const std::vector<std::string> &column)
1902 {
1903     int index;
1904     for (auto &columnValue : column) {
1905         err = resultSet->GetColumnIndex(columnValue, index);
1906         if (err != NativeRdb::E_OK) {
1907             continue;
1908         }
1909         if (columnValue == MEDIA_DATA_DB_ID) {
1910             ParseStringResult(resultSet, index, data.id, err);
1911         } else if (columnValue == MEDIA_DATA_DB_FILE_PATH) {
1912             ParseStringResult(resultSet, index, data.path, err);
1913         } else if (columnValue == MEDIA_DATA_DB_DATE_ADDED) {
1914             ParseStringResult(resultSet, index, data.dateAdded, err);
1915         } else if (columnValue == MEDIA_DATA_DB_NAME) {
1916             ParseStringResult(resultSet, index, data.displayName, err);
1917         } else if (columnValue == MEDIA_DATA_DB_MEDIA_TYPE) {
1918             data.mediaType = MediaType::MEDIA_TYPE_ALL;
1919             err = resultSet->GetInt(index, data.mediaType);
1920         } else if (columnValue == MEDIA_DATA_DB_ORIENTATION) {
1921             err = resultSet->GetInt(index, data.orientation);
1922         } else if (columnValue == MEDIA_DATA_DB_POSITION) {
1923             int position = 0;
1924             err = resultSet->GetInt(index, position);
1925             data.isLocalFile = (position == 1);
1926         } else if (columnValue == MEDIA_DATA_DB_HEIGHT) {
1927             err = resultSet->GetInt(index, data.photoHeight);
1928         } else if (columnValue == MEDIA_DATA_DB_WIDTH) {
1929             err = resultSet->GetInt(index, data.photoWidth);
1930         }
1931     }
1932 
1933     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_TAKEN, index);
1934     if (err == NativeRdb::E_OK) {
1935         ParseStringResult(resultSet, index, data.dateTaken, err);
1936     }
1937 }
1938 
ResizeThumb(int & width,int & height)1939 bool ThumbnailUtils::ResizeThumb(int &width, int &height)
1940 {
1941     int maxLen = max(width, height);
1942     int minLen = min(width, height);
1943     if (minLen == 0) {
1944         MEDIA_ERR_LOG("Divisor minLen is 0");
1945         return false;
1946     }
1947     double ratio = static_cast<double>(maxLen) / minLen;
1948     if (minLen > SHORT_SIDE_THRESHOLD) {
1949         minLen = SHORT_SIDE_THRESHOLD;
1950         maxLen = static_cast<int>(SHORT_SIDE_THRESHOLD * ratio);
1951         if (maxLen > MAXIMUM_SHORT_SIDE_THRESHOLD) {
1952             maxLen = MAXIMUM_SHORT_SIDE_THRESHOLD;
1953         }
1954         if (height > width) {
1955             width = minLen;
1956             height = maxLen;
1957         } else {
1958             width = maxLen;
1959             height = minLen;
1960         }
1961     }
1962     if (minLen <= SHORT_SIDE_THRESHOLD && maxLen > SHORT_SIDE_THRESHOLD && ratio > ASPECT_RATIO_THRESHOLD) {
1963         int newMaxLen = static_cast<int>(minLen * ASPECT_RATIO_THRESHOLD);
1964         if (height > width) {
1965             width = minLen;
1966             height = newMaxLen;
1967         } else {
1968             width = newMaxLen;
1969             height = minLen;
1970         }
1971     }
1972     return true;
1973 }
1974 
ResizeLcd(int & width,int & height)1975 bool ThumbnailUtils::ResizeLcd(int &width, int &height)
1976 {
1977     int maxLen = max(width, height);
1978     int minLen = min(width, height);
1979     if (minLen == 0) {
1980         MEDIA_ERR_LOG("Divisor minLen is 0");
1981         return false;
1982     }
1983     double ratio = static_cast<double>(maxLen) / minLen;
1984     if (std::abs(ratio) < EPSILON) {
1985         MEDIA_ERR_LOG("ratio is 0");
1986         return false;
1987     }
1988     int newMaxLen = maxLen;
1989     int newMinLen = minLen;
1990     if (maxLen > LCD_LONG_SIDE_THRESHOLD) {
1991         newMaxLen = LCD_LONG_SIDE_THRESHOLD;
1992         newMinLen = static_cast<int>(newMaxLen / ratio);
1993     }
1994     int lastMinLen = newMinLen;
1995     int lastMaxLen = newMaxLen;
1996     if (newMinLen < LCD_SHORT_SIDE_THRESHOLD && minLen >= LCD_SHORT_SIDE_THRESHOLD) {
1997         lastMinLen = LCD_SHORT_SIDE_THRESHOLD;
1998         lastMaxLen = static_cast<int>(lastMinLen * ratio);
1999         if (lastMaxLen > MAXIMUM_LCD_LONG_SIDE) {
2000             lastMaxLen = MAXIMUM_LCD_LONG_SIDE;
2001             lastMinLen = static_cast<int>(lastMaxLen / ratio);
2002         }
2003     }
2004 
2005     // When LCD size has changed after resize, check if width or height is odd number
2006     // Add one to the odd side to make sure LCD would be compressed through hardware encode
2007     if (max(width, height) != lastMaxLen) {
2008         lastMaxLen += lastMaxLen % EVEN_BASE_NUMBER;
2009         lastMinLen += lastMinLen % EVEN_BASE_NUMBER;
2010     }
2011     if (height > width) {
2012         width = lastMinLen;
2013         height = lastMaxLen;
2014     } else {
2015         width = lastMaxLen;
2016         height = lastMinLen;
2017     }
2018     return true;
2019 }
2020 
IsSupportGenAstc()2021 bool ThumbnailUtils::IsSupportGenAstc()
2022 {
2023     return ImageSource::IsSupportGenAstc();
2024 }
2025 
SaveAstcDataToKvStore(ThumbnailData & data,const ThumbnailType & type)2026 int ThumbnailUtils::SaveAstcDataToKvStore(ThumbnailData &data, const ThumbnailType &type)
2027 {
2028     string key;
2029     if (!MediaFileUtils::GenerateKvStoreKey(data.id, data.dateTaken, key)) {
2030         MEDIA_ERR_LOG("GenerateKvStoreKey failed");
2031         return E_ERR;
2032     }
2033 
2034     std::shared_ptr<MediaLibraryKvStore> kvStore;
2035     if (type == ThumbnailType::MTH_ASTC) {
2036         kvStore = MediaLibraryKvStoreManager::GetInstance()
2037             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
2038     } else if (type == ThumbnailType::YEAR_ASTC) {
2039         kvStore = MediaLibraryKvStoreManager::GetInstance()
2040             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
2041     } else {
2042         MEDIA_ERR_LOG("invalid thumbnailType");
2043         return E_ERR;
2044     }
2045     if (kvStore == nullptr) {
2046         MEDIA_ERR_LOG("kvStore is nullptr");
2047         return E_ERR;
2048     }
2049     int32_t count = 0;
2050     kvStore->GetCount(key, count);
2051     data.isThumbExisted = count > 0;
2052     int status = kvStore->Insert(key, type == ThumbnailType::MTH_ASTC ? data.monthAstc : data.yearAstc);
2053     if (status != E_OK) {
2054         MEDIA_ERR_LOG("Insert failed, type:%{public}d, field_id:%{public}s, status:%{public}d",
2055             type, key.c_str(), status);
2056         return E_ERR;
2057     }
2058     MEDIA_INFO_LOG("type:%{public}d, field_id:%{public}s, status:%{public}d", type, key.c_str(), status);
2059     return status;
2060 }
2061 
CheckDateTaken(ThumbRdbOpt & opts,ThumbnailData & data)2062 bool ThumbnailUtils::CheckDateTaken(ThumbRdbOpt &opts, ThumbnailData &data)
2063 {
2064     if (!data.dateTaken.empty()) {
2065         return true;
2066     }
2067 
2068     vector<string> column = {
2069         MEDIA_DATA_DB_DATE_TAKEN,
2070     };
2071     vector<string> selectionArgs;
2072     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + data.id;
2073     RdbPredicates rdbPredicates(opts.table);
2074     rdbPredicates.SetWhereClause(strQueryCondition);
2075     rdbPredicates.SetWhereArgs(selectionArgs);
2076     if (opts.store == nullptr) {
2077         MEDIA_ERR_LOG("opts.store is nullptr");
2078         return false;
2079     }
2080     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
2081 
2082     int err;
2083     if (!CheckResultSetCount(resultSet, err)) {
2084         MEDIA_ERR_LOG("CheckResultSetCount failed, err: %{public}d", err);
2085         return false;
2086     }
2087     err = resultSet->GoToFirstRow();
2088     if (err != E_OK) {
2089         MEDIA_ERR_LOG("GoToFirstRow failed, err: %{public}d", err);
2090         return false;
2091     }
2092 
2093     int index;
2094     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_TAKEN, index);
2095     if (err == NativeRdb::E_OK) {
2096         ParseStringResult(resultSet, index, data.dateTaken, err);
2097     } else {
2098         MEDIA_ERR_LOG("GetColumnIndex failed, err: %{public}d", err);
2099         resultSet->Close();
2100         return false;
2101     }
2102     resultSet->Close();
2103     return true;
2104 }
2105 
QueryThumbnailDataFromFileId(ThumbRdbOpt & opts,const std::string & id,ThumbnailData & data,int & err)2106 void ThumbnailUtils::QueryThumbnailDataFromFileId(ThumbRdbOpt &opts, const std::string &id,
2107     ThumbnailData &data, int &err)
2108 {
2109     if (opts.table.empty()) {
2110         MEDIA_ERR_LOG("Table is empty");
2111         return;
2112     }
2113     RdbPredicates predicates(opts.table);
2114     predicates.EqualTo(MediaColumn::MEDIA_ID, id);
2115     vector<string> columns = {
2116         MEDIA_DATA_DB_ID,
2117         MEDIA_DATA_DB_FILE_PATH,
2118         MEDIA_DATA_DB_HEIGHT,
2119         MEDIA_DATA_DB_WIDTH,
2120         MEDIA_DATA_DB_MEDIA_TYPE,
2121         MEDIA_DATA_DB_DATE_ADDED,
2122         MEDIA_DATA_DB_ORIENTATION,
2123         MEDIA_DATA_DB_POSITION,
2124         MEDIA_DATA_DB_DATE_TAKEN,
2125     };
2126     if (opts.store == nullptr) {
2127         MEDIA_ERR_LOG("opts.store is nullptr");
2128         return;
2129     }
2130     auto resultSet = opts.store->QueryByStep(predicates, columns);
2131     if (resultSet == nullptr) {
2132         MEDIA_ERR_LOG("ResultSet is nullptr");
2133         return;
2134     }
2135     err = resultSet->GoToFirstRow();
2136     if (err != NativeRdb::E_OK) {
2137         MEDIA_ERR_LOG("Fail to GoToFirstRow");
2138         resultSet->Close();
2139         return;
2140     }
2141 
2142     ParseQueryResult(resultSet, data, err, columns);
2143     if (err != NativeRdb::E_OK || data.path.empty()) {
2144         MEDIA_ERR_LOG("Fail to query thumbnail data using id: %{public}s, err: %{public}d", id.c_str(), err);
2145         resultSet->Close();
2146         return;
2147     }
2148     resultSet->Close();
2149     data.stats.uri = data.path;
2150 }
2151 
DeleteAstcDataFromKvStore(ThumbRdbOpt & opts,const ThumbnailType & type)2152 bool ThumbnailUtils::DeleteAstcDataFromKvStore(ThumbRdbOpt &opts, const ThumbnailType &type)
2153 {
2154     string key;
2155     if (!MediaFileUtils::GenerateKvStoreKey(opts.row, opts.dateTaken, key)) {
2156         MEDIA_ERR_LOG("GenerateKvStoreKey failed");
2157         return false;
2158     }
2159 
2160     std::shared_ptr<MediaLibraryKvStore> kvStore;
2161     if (type == ThumbnailType::MTH_ASTC) {
2162         kvStore = MediaLibraryKvStoreManager::GetInstance()
2163             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
2164     } else if (type == ThumbnailType::YEAR_ASTC) {
2165         kvStore = MediaLibraryKvStoreManager::GetInstance()
2166             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
2167     } else {
2168         MEDIA_ERR_LOG("invalid thumbnailType");
2169         return false;
2170     }
2171     if (kvStore == nullptr) {
2172         MEDIA_ERR_LOG("kvStore is nullptr");
2173         return false;
2174     }
2175 
2176     int status = kvStore->Delete(key);
2177     return status == E_OK;
2178 }
2179 
UpdateAstcDateTakenFromKvStore(ThumbRdbOpt & opts,const ThumbnailData & data)2180 bool ThumbnailUtils::UpdateAstcDateTakenFromKvStore(ThumbRdbOpt &opts, const ThumbnailData &data)
2181 {
2182     std::string formerKey;
2183     std::string newKey;
2184     if (!MediaFileUtils::GenerateKvStoreKey(opts.row, opts.dateTaken, formerKey) ||
2185         !MediaFileUtils::GenerateKvStoreKey(opts.row, data.dateTaken, newKey)) {
2186         MEDIA_ERR_LOG("UpdateAstcDateTakenFromKvStore GenerateKvStoreKey failed");
2187         return false;
2188     }
2189 
2190     std::shared_ptr<MediaLibraryKvStore> monthKvStore;
2191     std::shared_ptr<MediaLibraryKvStore> yearKvStore;
2192     monthKvStore = MediaLibraryKvStoreManager::GetInstance()
2193         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
2194     yearKvStore = MediaLibraryKvStoreManager::GetInstance()
2195         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
2196     if (monthKvStore == nullptr || yearKvStore == nullptr) {
2197         MEDIA_ERR_LOG("kvStore is nullptr");
2198         return false;
2199     }
2200 
2201     std::vector<uint8_t> monthValue;
2202     if (monthKvStore->Query(formerKey, monthValue) != E_OK || monthKvStore->Insert(newKey, monthValue) != E_OK) {
2203         MEDIA_ERR_LOG("MonthValue update failed, fileId %{public}s", opts.row.c_str());
2204         return false;
2205     }
2206     std::vector<uint8_t> yearValue;
2207     if (yearKvStore->Query(formerKey, yearValue) != E_OK || yearKvStore->Insert(newKey, yearValue) != E_OK) {
2208         MEDIA_ERR_LOG("YearValue update failed, fileId %{public}s", opts.row.c_str());
2209         return false;
2210     }
2211 
2212     int status = monthKvStore->Delete(formerKey) && yearKvStore->Delete(formerKey);
2213     if (status != E_OK) {
2214         MEDIA_ERR_LOG("Former kv delete failed, fileId %{public}s", opts.row.c_str());
2215         return false;
2216     }
2217     return true;
2218 }
2219 
GetThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & outData)2220 void ThumbnailUtils::GetThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &outData)
2221 {
2222     if (opts.store == nullptr) {
2223         return;
2224     }
2225     if (!opts.path.empty()) {
2226         outData.path = opts.path;
2227         outData.id = opts.row;
2228         outData.dateTaken = opts.dateTaken;
2229         outData.fileUri = opts.fileUri;
2230         outData.stats.uri = outData.fileUri;
2231         return;
2232     }
2233     string filesTableName = opts.table;
2234     int errCode = E_ERR;
2235     if (!opts.networkId.empty()) {
2236         filesTableName = opts.store->ObtainDistributedTableName(opts.networkId, opts.table, errCode);
2237     }
2238     if (filesTableName.empty()) {
2239         return;
2240     }
2241     opts.table = filesTableName;
2242     int err;
2243     ThumbnailUtils::QueryThumbnailInfo(opts, outData, err);
2244     if (err != E_OK) {
2245         MEDIA_ERR_LOG("query fail [%{public}d]", err);
2246     }
2247 }
2248 
ScaleThumbnailFromSource(ThumbnailData & data,bool isSourceEx)2249 bool ThumbnailUtils::ScaleThumbnailFromSource(ThumbnailData &data, bool isSourceEx)
2250 {
2251     std::shared_ptr<PixelMap> dataSource = isSourceEx ? data.source.GetPixelMapEx() : data.source.GetPixelMap();
2252     if (dataSource == nullptr) {
2253         MEDIA_ERR_LOG("Fail to scale thumbnail, data source is empty, isSourceEx: %{public}d.", isSourceEx);
2254         return false;
2255     }
2256     if (dataSource != nullptr && dataSource->IsHdr()) {
2257         uint32_t ret = dataSource->ToSdr();
2258         if (ret != E_OK) {
2259             MEDIA_ERR_LOG("Fail to transform to sdr, isSourceEx: %{public}d.", isSourceEx);
2260             return false;
2261         }
2262     }
2263     ImageInfo imageInfo;
2264     dataSource->GetImageInfo(imageInfo);
2265     if (imageInfo.pixelFormat != PixelFormat::RGBA_8888) {
2266         uint32_t ret = ImageFormatConvert::ConvertImageFormat(dataSource, PixelFormat::RGBA_8888);
2267         if (ret != E_OK) {
2268             MEDIA_ERR_LOG("Fail to scale convert image format, isSourceEx: %{public}d, format: %{public}d.",
2269                 isSourceEx, imageInfo.pixelFormat);
2270             return false;
2271         }
2272     }
2273     if (isSourceEx) {
2274         data.source.SetPixelMapEx(dataSource);
2275     } else {
2276         data.source.SetPixelMap(dataSource);
2277     }
2278     Size desiredSize;
2279     Size targetSize = ConvertDecodeSize(data, {dataSource->GetWidth(), dataSource->GetHeight()}, desiredSize);
2280     if (!ScaleTargetPixelMap(dataSource, targetSize, Media::AntiAliasingOption::HIGH)) {
2281         MEDIA_ERR_LOG("Fail to scale to targetSize");
2282         return false;
2283     }
2284     if (!CenterScaleEx(dataSource, desiredSize, data.path)) {
2285         MEDIA_ERR_LOG("ScaleThumbnailFromSource center crop failed, path: %{public}s, isSourceEx: %{public}d.",
2286             DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
2287         return false;
2288     }
2289     return true;
2290 }
2291 
RecordStartGenerateStats(ThumbnailData::GenerateStats & stats,GenerateScene scene,LoadSourceType sourceType)2292 void ThumbnailUtils::RecordStartGenerateStats(ThumbnailData::GenerateStats &stats,
2293     GenerateScene scene, LoadSourceType sourceType)
2294 {
2295     stats.startTime = MediaFileUtils::UTCTimeMilliSeconds();
2296     stats.scene = scene;
2297     stats.sourceType = sourceType;
2298 }
2299 
RecordCostTimeAndReport(ThumbnailData::GenerateStats & stats)2300 void ThumbnailUtils::RecordCostTimeAndReport(ThumbnailData::GenerateStats &stats)
2301 {
2302     stats.totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - stats.startTime);
2303     DfxManager::GetInstance()->HandleThumbnailGeneration(stats);
2304 }
2305 
GetLocalThumbSize(const ThumbnailData & data,const ThumbnailType & type,Size & size)2306 bool ThumbnailUtils::GetLocalThumbSize(const ThumbnailData &data, const ThumbnailType& type, Size& size)
2307 {
2308     if (type != ThumbnailType::THUMB && type != ThumbnailType::LCD && type != ThumbnailType::THUMB_ASTC) {
2309         MEDIA_ERR_LOG("can not get size for such type: %{public}d", type);
2310         return false;
2311     }
2312     std::string tmpPath = "";
2313     switch (type) {
2314         case ThumbnailType::THUMB:
2315         case ThumbnailType::THUMB_ASTC:
2316             tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
2317             break;
2318         case ThumbnailType::LCD:
2319             tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
2320             break;
2321         default:
2322             break;
2323     }
2324     uint32_t err = 0;
2325     SourceOptions opts;
2326     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(tmpPath, opts, err);
2327     if (err != E_OK || imageSource == nullptr) {
2328         MEDIA_ERR_LOG("Failed to LoadImageSource for path:%{public}s", DfxUtils::GetSafePath(tmpPath).c_str());
2329         return false;
2330     }
2331     ImageInfo imageInfo;
2332     err = imageSource->GetImageInfo(0, imageInfo);
2333     if (err != E_OK) {
2334         MEDIA_ERR_LOG("Failed to Get ImageInfo, path:%{public}s", DfxUtils::GetSafePath(tmpPath).c_str());
2335         return false;
2336     }
2337     size.height = imageInfo.size.height;
2338     size.width = imageInfo.size.width;
2339     return true;
2340 }
2341 
SetThumbnailSizeValue(NativeRdb::ValuesBucket & values,Size & size,const std::string & column)2342 void ThumbnailUtils::SetThumbnailSizeValue(NativeRdb::ValuesBucket& values, Size& size, const std::string& column)
2343 {
2344     if (size.height == 0 || size.width == 0) {
2345         return;
2346     }
2347     std::string tmpSize = std::to_string(size.width) + ":" + std::to_string(size.height);
2348     values.PutString(column, tmpSize);
2349 }
2350 
IsMobileNetworkEnabled()2351 static bool IsMobileNetworkEnabled()
2352 {
2353     bool isWifiConnected = false;
2354     auto wifiDevicePtr = Wifi::WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
2355     if (wifiDevicePtr == nullptr) {
2356         MEDIA_ERR_LOG("wifiDevicePtr is null");
2357     } else {
2358         int32_t ret = wifiDevicePtr->IsConnected(isWifiConnected);
2359         if (ret != Wifi::WIFI_OPT_SUCCESS) {
2360             MEDIA_ERR_LOG("Get Is Connnected Fail: %{public}d", ret);
2361         }
2362     }
2363     if (isWifiConnected) {
2364         return true;
2365     }
2366     auto saMgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
2367     if (saMgr == nullptr) {
2368         MEDIA_ERR_LOG("Failed to get SystemAbilityManagerClient");
2369         return false;
2370     }
2371     OHOS::sptr<OHOS::IRemoteObject> remoteObject = saMgr->CheckSystemAbility(STORAGE_MANAGER_MANAGER_ID);
2372     if (remoteObject == nullptr) {
2373         MEDIA_ERR_LOG("Token is null.");
2374         return false;
2375     }
2376     std::shared_ptr<DataShare::DataShareHelper> cloudHelper =
2377         DataShare::DataShareHelper::Creator(remoteObject, CLOUD_DATASHARE_URI);
2378     if (cloudHelper == nullptr) {
2379         MEDIA_INFO_LOG("cloudHelper is null");
2380         return false;
2381     }
2382     DataShare::DataSharePredicates predicates;
2383     predicates.EqualTo("key", "useMobileNetworkData");
2384     Uri cloudUri(CLOUD_DATASHARE_URI + "&key=useMobileNetworkData");
2385     vector<string> columns = {"value"};
2386     shared_ptr<DataShare::DataShareResultSet> resultSet =
2387         cloudHelper->Query(cloudUri, predicates, columns);
2388 
2389     //default mobile network is off
2390     string switchOn = "0";
2391     if (resultSet != nullptr && resultSet->GoToNextRow()==0) {
2392         resultSet->GetString(0, switchOn);
2393     }
2394     if (resultSet != nullptr) {
2395         resultSet->Close();
2396     }
2397     cloudHelper->Release();
2398     return switchOn == "1";
2399 }
2400 
QueryNoAstcInfosOnDemand(ThumbRdbOpt & opts,std::vector<ThumbnailData> & infos,NativeRdb::RdbPredicates & rdbPredicate,int & err)2401 bool ThumbnailUtils::QueryNoAstcInfosOnDemand(ThumbRdbOpt &opts,
2402     std::vector<ThumbnailData> &infos, NativeRdb::RdbPredicates &rdbPredicate, int &err)
2403 {
2404     vector<string> column = {
2405         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_HEIGHT, MEDIA_DATA_DB_WIDTH,
2406         MEDIA_DATA_DB_POSITION, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_NAME,
2407         MEDIA_DATA_DB_ORIENTATION,
2408         MEDIA_DATA_DB_DATE_TAKEN,
2409     };
2410     rdbPredicate.EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "0");
2411     if (!IsMobileNetworkEnabled()) {
2412         rdbPredicate.BeginWrap();
2413         rdbPredicate.EqualTo(PhotoColumn::PHOTO_POSITION, "1");
2414         rdbPredicate.Or();
2415         rdbPredicate.EqualTo(PhotoColumn::PHOTO_POSITION, "3");
2416         rdbPredicate.EndWrap();
2417     }
2418     rdbPredicate.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
2419     rdbPredicate.EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, "0");
2420     rdbPredicate.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
2421     rdbPredicate.EqualTo(COMPAT_HIDDEN, "0");
2422     rdbPredicate.Limit(THUMBNAIL_GENERATE_BATCH_COUNT);
2423     if (opts.store == nullptr) {
2424         MEDIA_ERR_LOG("opts.store is nullptr");
2425         return false;
2426     }
2427     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicate, column);
2428     if (!CheckResultSetCount(resultSet, err)) {
2429         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
2430         if (err == E_EMPTY_VALUES_BUCKET) {
2431             return true;
2432         }
2433         return false;
2434     }
2435     err = resultSet->GoToFirstRow();
2436     if (err != E_OK) {
2437         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
2438         return false;
2439     }
2440 
2441     ThumbnailData data;
2442     do {
2443         ParseQueryResult(resultSet, data, err, column);
2444         if (!data.path.empty()) {
2445             infos.push_back(data);
2446         }
2447     } while (resultSet->GoToNextRow() == E_OK);
2448     return true;
2449 }
2450 
ConvertStrToInt32(const std::string & str,int32_t & ret)2451 bool ThumbnailUtils::ConvertStrToInt32(const std::string &str, int32_t &ret)
2452 {
2453     if (str.empty() || str.length() > INT32_MAX_VALUE_LENGTH) {
2454         MEDIA_ERR_LOG("convert failed, str = %{public}s", str.c_str());
2455         return false;
2456     }
2457     if (!IsNumericStr(str)) {
2458         MEDIA_ERR_LOG("convert failed, input is not number, str = %{public}s", str.c_str());
2459         return false;
2460     }
2461     int64_t numberValue = std::stoll(str);
2462     if (numberValue < INT32_MIN || numberValue > INT32_MAX) {
2463         MEDIA_ERR_LOG("convert failed, Input is out of range, str = %{public}s", str.c_str());
2464         return false;
2465     }
2466     ret = static_cast<int32_t>(numberValue);
2467     return true;
2468 }
2469 
CheckCloudThumbnailDownloadFinish(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr)2470 bool ThumbnailUtils::CheckCloudThumbnailDownloadFinish(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr)
2471 {
2472     if (rdbStorePtr == nullptr) {
2473         MEDIA_ERR_LOG("RdbStorePtr is nullptr!");
2474         return false;
2475     }
2476 
2477     RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
2478     vector<string> column = { "count(1) AS count" };
2479     rdbPredicates.BeginWrap()
2480         ->GreaterThanOrEqualTo(PhotoColumn::PHOTO_POSITION, CLOUD_PHOTO_POSITION)
2481         ->And()
2482         ->NotEqualTo(PhotoColumn::PHOTO_THUMB_STATUS, CLOUD_THUMB_STATUS_DOWNLOAD)
2483         ->EndWrap();
2484     shared_ptr<ResultSet> resultSet = rdbStorePtr->Query(rdbPredicates, column);
2485     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2486         MEDIA_ERR_LOG("ResultSet is null!");
2487         return false;
2488     }
2489 
2490     int32_t count = GetInt32Val(RDB_QUERY_COUNT, resultSet);
2491     MEDIA_INFO_LOG("Number of undownloaded cloud images: %{public}d", count);
2492     if (count > CLOUD_THUMBNAIL_DOWNLOAD_FINISH_NUMBER) {
2493         return false;
2494     }
2495     return true;
2496 }
2497 
QueryOldKeyAstcInfos(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr,const std::string & table,std::vector<ThumbnailData> & infos)2498 bool ThumbnailUtils::QueryOldKeyAstcInfos(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr,
2499     const std::string &table, std::vector<ThumbnailData> &infos)
2500 {
2501     vector<string> column = {
2502         MEDIA_DATA_DB_ID,
2503         MEDIA_DATA_DB_DATE_ADDED,
2504         MEDIA_DATA_DB_DATE_TAKEN,
2505     };
2506     RdbPredicates rdbPredicates(table);
2507     rdbPredicates.GreaterThanOrEqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "3");
2508     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
2509     shared_ptr<ResultSet> resultSet = rdbStorePtr->QueryByStep(rdbPredicates, column);
2510     int err = 0;
2511     if (!CheckResultSetCount(resultSet, err)) {
2512         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
2513         if (err == E_EMPTY_VALUES_BUCKET) {
2514             return true;
2515         }
2516         return false;
2517     }
2518     err = resultSet->GoToFirstRow();
2519     if (err != E_OK) {
2520         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
2521         return false;
2522     }
2523 
2524     ThumbnailData data;
2525     do {
2526         ParseQueryResult(resultSet, data, err, column);
2527         infos.push_back(data);
2528     } while (resultSet->GoToNextRow() == E_OK);
2529     return true;
2530 }
2531 } // namespace Media
2532 } // namespace OHOS
2533