• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define MLOG_TAG "Thumbnail"
16 
17 #include "thumbnail_utils.h"
18 
19 #include <fcntl.h>
20 #include <malloc.h>
21 #include <sys/stat.h>
22 
23 #include "cloud_sync_helper.h"
24 #include "datashare_abs_result_set.h"
25 #ifdef DISTRIBUTED
26 #include "device_manager.h"
27 #endif
28 #include "distributed_kv_data_manager.h"
29 #include "hitrace_meter.h"
30 #include "image_packer.h"
31 #include "ipc_skeleton.h"
32 #include "media_column.h"
33 #include "medialibrary_common_utils.h"
34 #include "medialibrary_errno.h"
35 #include "medialibrary_kvstore_manager.h"
36 #include "medialibrary_sync_operation.h"
37 #include "medialibrary_tracer.h"
38 #include "media_file_utils.h"
39 #include "media_log.h"
40 #include "mimetype_utils.h"
41 #include "parameter.h"
42 #include "post_proc.h"
43 #include "rdb_errno.h"
44 #include "rdb_predicates.h"
45 #include "thumbnail_const.h"
46 #include "unique_fd.h"
47 #include "post_event_utils.h"
48 
49 using namespace std;
50 using namespace OHOS::DistributedKv;
51 using namespace OHOS::NativeRdb;
52 
53 namespace OHOS {
54 namespace Media {
55 constexpr float EPSILON = 1e-6;
56 constexpr int32_t SHORT_SIDE_THRESHOLD = 256;
57 constexpr int32_t MAXIMUM_SHORT_SIDE_THRESHOLD = 768;
58 constexpr int32_t LCD_SHORT_SIDE_THRESHOLD = 512;
59 constexpr int32_t LCD_LONG_SIDE_THRESHOLD = 1920;
60 constexpr int32_t MAXIMUM_LCD_LONG_SIDE = 4096;
61 constexpr int32_t ASPECT_RATIO_THRESHOLD = 3;
62 constexpr int32_t MIN_COMPRESS_BUF_SIZE = 8192;
63 constexpr int32_t MAX_FIELD_LENGTH = 10;
64 constexpr int32_t MAX_TIMEID_LENGTH = 10;
65 constexpr int32_t DECODE_SCALE_BASE = 2;
66 const std::string KVSTORE_KEY_TEMPLATE = "0000000000";
67 
68 #ifdef DISTRIBUTED
DeleteDistributeLcdData(ThumbRdbOpt & opts,ThumbnailData & thumbnailData)69 bool ThumbnailUtils::DeleteDistributeLcdData(ThumbRdbOpt &opts, ThumbnailData &thumbnailData)
70 {
71     if (thumbnailData.lcdKey.empty()) {
72         MEDIA_ERR_LOG("lcd Key is empty");
73         return false;
74     }
75 
76     if (IsImageExist(thumbnailData.lcdKey, opts.networkId, opts.kvStore)) {
77         if (!RemoveDataFromKv(opts.kvStore, thumbnailData.lcdKey)) {
78             MEDIA_ERR_LOG("ThumbnailUtils::RemoveDataFromKv faild");
79             return false;
80         }
81         if (!CleanDistributeLcdInfo(opts)) {
82             return false;
83         }
84     }
85 
86     return true;
87 }
88 #endif
89 
GetThumbnailSuffix(ThumbnailType type)90 static string GetThumbnailSuffix(ThumbnailType type)
91 {
92     string suffix;
93     switch (type) {
94         case ThumbnailType::THUMB:
95             suffix = THUMBNAIL_THUMB_SUFFIX;
96             break;
97         case ThumbnailType::THUMB_ASTC:
98             suffix = THUMBNAIL_THUMBASTC_SUFFIX;
99             break;
100         case ThumbnailType::LCD:
101             suffix = THUMBNAIL_LCD_SUFFIX;
102             break;
103         default:
104             return "";
105     }
106     return suffix;
107 }
108 
DeleteThumbFile(ThumbnailData & data,ThumbnailType type)109 bool ThumbnailUtils::DeleteThumbFile(ThumbnailData &data, ThumbnailType type)
110 {
111     string fileName = GetThumbnailPath(data.path, GetThumbnailSuffix(type));
112     if (!MediaFileUtils::DeleteFile(fileName)) {
113         MEDIA_ERR_LOG("delete file faild %{public}d", errno);
114         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, -errno},
115             {KEY_OPT_FILE, fileName}, {KEY_OPT_TYPE, OptType::THUMB}};
116         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
117         return false;
118     }
119     return true;
120 }
121 
LoadAudioFileInfo(shared_ptr<AVMetadataHelper> avMetadataHelper,ThumbnailData & data,const bool isThumbnail,Size & desiredSize,uint32_t & errCode)122 bool ThumbnailUtils::LoadAudioFileInfo(shared_ptr<AVMetadataHelper> avMetadataHelper, ThumbnailData &data,
123     const bool isThumbnail, Size &desiredSize, uint32_t &errCode)
124 {
125     auto audioPicMemory = avMetadataHelper->FetchArtPicture();
126     if (audioPicMemory == nullptr) {
127         MEDIA_ERR_LOG("FetchArtPicture failed!");
128         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
129             {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
130         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
131         return false;
132     }
133 
134     SourceOptions opts;
135     unique_ptr<ImageSource> audioImageSource = ImageSource::CreateImageSource(audioPicMemory->GetBase(),
136         audioPicMemory->GetSize(), opts, errCode);
137     if (audioImageSource == nullptr) {
138         MEDIA_ERR_LOG("Failed to create image source! path %{private}s errCode %{public}d", data.path.c_str(), errCode);
139         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
140             {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
141         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
142         return false;
143     }
144 
145     ImageInfo imageInfo;
146     errCode = audioImageSource->GetImageInfo(0, imageInfo);
147     if (errCode != E_OK) {
148         MEDIA_ERR_LOG("Failed to get image info, path: %{private}s err: %{public}d", data.path.c_str(), errCode);
149         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
150             {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
151         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
152         return false;
153     }
154 
155     DecodeOptions decOpts;
156     decOpts.desiredSize = ConvertDecodeSize(imageInfo.size, desiredSize, isThumbnail);
157     decOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
158     data.source = audioImageSource->CreatePixelMap(decOpts, errCode);
159     if ((errCode != E_OK) || (data.source == nullptr)) {
160         MEDIA_ERR_LOG("Av meta data helper fetch frame at time failed");
161         if (errCode != E_OK) {
162             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
163                 {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, data.path},
164                 {KEY_OPT_TYPE, OptType::THUMB}};
165             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
166         }
167         return false;
168     }
169     return true;
170 }
171 
LoadAudioFile(ThumbnailData & data,const bool isThumbnail,Size & desiredSize)172 bool ThumbnailUtils::LoadAudioFile(ThumbnailData &data, const bool isThumbnail, Size &desiredSize)
173 {
174     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
175     string path = data.path;
176     int32_t err = SetSource(avMetadataHelper, path);
177     if (err != E_OK) {
178         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
179             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
180         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
181 
182         MEDIA_ERR_LOG("Av meta data helper set source failed %{public}d", err);
183         return false;
184     }
185     uint32_t errCode = 0;
186     if (!LoadAudioFileInfo(avMetadataHelper, data, isThumbnail, desiredSize, errCode)) {
187         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
188             {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
189         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
190         return false;
191     }
192     return true;
193 }
194 
LoadVideoFile(ThumbnailData & data,const bool isThumbnail,Size & desiredSize)195 bool ThumbnailUtils::LoadVideoFile(ThumbnailData &data, const bool isThumbnail, Size &desiredSize)
196 {
197     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
198     string path = data.path;
199     int32_t err = SetSource(avMetadataHelper, path);
200     if (err != 0) {
201         MEDIA_ERR_LOG("Av meta data helper set source failed path %{private}s err %{public}d",
202             path.c_str(), err);
203         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
204             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
205         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
206         return false;
207     }
208     PixelMapParams param;
209     param.colorFormat = PixelFormat::RGBA_8888;
210     data.source = avMetadataHelper->FetchFrameAtTime(AV_FRAME_TIME, AVMetadataQueryOption::AV_META_QUERY_NEXT_SYNC,
211         param);
212     if (data.source == nullptr) {
213         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
214             {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
215         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
216         return false;
217     }
218     int width = data.source->GetWidth();
219     int height = data.source->GetHeight();
220     if (!isThumbnail && !ResizeLcd(width, height)) {
221         MEDIA_ERR_LOG("ResizeLcd failed");
222     } else if (isThumbnail && !ResizeThumb(width, height)) {
223         MEDIA_ERR_LOG("ResizeThumb failed");
224     }
225     desiredSize = {width, height};
226     if ((width != data.source->GetWidth() || height != data.source->GetHeight())) {
227         param.dstWidth = width;
228         param.dstHeight = height;
229         data.source = avMetadataHelper->FetchFrameAtTime(AV_FRAME_TIME, AVMetadataQueryOption::AV_META_QUERY_NEXT_SYNC,
230             param);
231         if (data.source == nullptr) {
232             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
233                 {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
234             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
235             return false;
236         }
237     }
238     auto resultMap = avMetadataHelper->ResolveMetadata();
239     string videoOrientation = resultMap.at(AV_KEY_VIDEO_ORIENTATION);
240     if (!videoOrientation.empty()) {
241         std::istringstream iss(videoOrientation);
242         iss >> data.degrees;
243     }
244     return true;
245 }
246 
247 // gen pixelmap from data.souce, should ensure source is not null
GenTargetPixelmap(ThumbnailData & data,const Size & desiredSize)248 bool ThumbnailUtils::GenTargetPixelmap(ThumbnailData &data, const Size &desiredSize)
249 {
250     MediaLibraryTracer tracer;
251     tracer.Start("GenTargetPixelmap");
252     if (data.source == nullptr) {
253         return false;
254     }
255 
256     if (!ScaleFastThumb(data, desiredSize)) {
257         return false;
258     }
259 
260     float widthScale = (1.0f * desiredSize.width) / data.source->GetWidth();
261     float heightScale = (1.0f * desiredSize.height) / data.source->GetHeight();
262     data.source->scale(widthScale, heightScale);
263     return true;
264 }
265 
ScaleTargetPixelMap(ThumbnailData & data,const Size & targetSize)266 bool ThumbnailUtils::ScaleTargetPixelMap(ThumbnailData &data, const Size &targetSize)
267 {
268     MediaLibraryTracer tracer;
269     tracer.Start("ImageSource::ScaleTargetPixelMap");
270 
271     PostProc postProc;
272     if (!postProc.ScalePixelMapEx(targetSize, *data.source, Media::AntiAliasingOption::HIGH)) {
273         MEDIA_ERR_LOG("thumbnail scale failed [%{private}s]", data.id.c_str());
274         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
275             {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
276         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
277         return false;
278     }
279     return true;
280 }
281 
NeedAutoResize(const Size & size)282 bool NeedAutoResize(const Size &size)
283 {
284     // Only small thumbnails need to be scaled after decoding, others should resized while decoding.
285     return size.width > SHORT_SIDE_THRESHOLD && size.height > SHORT_SIDE_THRESHOLD;
286 }
287 
GenDecodeOpts(const Size & sourceSize,const Size & targetSize,DecodeOptions & decodeOpts)288 bool GenDecodeOpts(const Size &sourceSize, const Size &targetSize, DecodeOptions &decodeOpts)
289 {
290     if (targetSize.width == 0) {
291         MEDIA_ERR_LOG("Failed to generate decodeOpts, scale size contains zero");
292         return false;
293     }
294     decodeOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
295     if (NeedAutoResize(targetSize)) {
296         decodeOpts.desiredSize = targetSize;
297         return true;
298     }
299 
300     int32_t decodeScale = 1;
301     int32_t scaleFactor = sourceSize.width / targetSize.width;
302     while (scaleFactor /= DECODE_SCALE_BASE) {
303         decodeScale *= DECODE_SCALE_BASE;
304     }
305     decodeOpts.desiredSize = {
306         std::ceil(sourceSize.width / decodeScale),
307         std::ceil(sourceSize.height / decodeScale),
308     };
309     return true;
310 }
311 
LoadImageSource(const std::string & path,uint32_t & err)312 unique_ptr<ImageSource> LoadImageSource(const std::string &path, uint32_t &err)
313 {
314     MediaLibraryTracer tracer;
315     tracer.Start("ImageSource::CreateImageSource");
316 
317     SourceOptions opts;
318     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(path, opts, err);
319     if (err != E_OK || !imageSource) {
320         MEDIA_ERR_LOG("Failed to create image source, path: %{private}s, err: %{public}d", path.c_str(), err);
321         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
322             {KEY_ERR_CODE, static_cast<int32_t>(err)}, {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
323         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
324         return imageSource;
325     }
326     return imageSource;
327 }
328 
LoadImageFile(ThumbnailData & data,const bool isThumbnail,Size & desiredSize,const std::string & targetPath)329 bool ThumbnailUtils::LoadImageFile(ThumbnailData &data, const bool isThumbnail, Size &desiredSize,
330     const std::string &targetPath)
331 {
332     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
333     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
334 
335     uint32_t err = E_OK;
336     std::string path = targetPath.empty() ? data.path : targetPath;
337 
338     unique_ptr<ImageSource> imageSource = LoadImageSource(path, err);
339     if (err != E_OK || !imageSource) {
340         return false;
341     }
342 
343     MediaLibraryTracer tracer;
344     tracer.Start("imageSource->CreatePixelMap");
345     ImageInfo imageInfo;
346     err = imageSource->GetImageInfo(0, imageInfo);
347     if (err != E_OK) {
348         MEDIA_ERR_LOG("Failed to get image info, path: %{private}s, err: %{public}d", path.c_str(), err);
349         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, static_cast<int32_t>(err)},
350             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
351         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
352         return false;
353     }
354 
355     DecodeOptions decodeOpts;
356     Size targetSize = ConvertDecodeSize(imageInfo.size, desiredSize, isThumbnail);
357     if (!GenDecodeOpts(imageInfo.size, targetSize, decodeOpts)) {
358         MEDIA_ERR_LOG("Failed to generate decodeOpts, pixelmap path %{private}s", path.c_str());
359         return false;
360     }
361     data.source = imageSource->CreatePixelMap(decodeOpts, err);
362     if ((err != E_OK) || (data.source == nullptr)) {
363         MEDIA_ERR_LOG("Failed to create pixelmap, path %{private}s, err %{public}d", path.c_str(), err);
364         if (err != E_OK) {
365             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
366                 {KEY_ERR_CODE, static_cast<int32_t>(err)}, {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
367             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
368         }
369         return false;
370     }
371     if (!NeedAutoResize(targetSize) && !ScaleTargetPixelMap(data, targetSize)) {
372         MEDIA_ERR_LOG("Failed to scale target, pixelmap path %{private}s", path.c_str());
373         return false;
374     }
375     tracer.Finish();
376 
377     int intTempMeta;
378     err = imageSource->GetImagePropertyInt(0, MEDIA_DATA_IMAGE_ORIENTATION, intTempMeta);
379     if (err == E_OK) {
380         data.degrees = static_cast<float>(intTempMeta);
381     }
382     return true;
383 }
384 
CompressImage(shared_ptr<PixelMap> & pixelMap,vector<uint8_t> & data,bool isHigh,shared_ptr<string> pathPtr,bool isAstc)385 bool ThumbnailUtils::CompressImage(shared_ptr<PixelMap> &pixelMap, vector<uint8_t> &data, bool isHigh,
386     shared_ptr<string> pathPtr, bool isAstc)
387 {
388     string path;
389     if (pathPtr != nullptr) {
390         path = *pathPtr;
391     }
392     PackOption option = {
393         .format = isAstc ? THUMBASTC_FORMAT : THUMBNAIL_FORMAT,
394         .quality = isAstc ? ASTC_LOW_QUALITY : (isHigh ? THUMBNAIL_HIGH : THUMBNAIL_MID),
395         .numberHint = NUMBER_HINT_1
396     };
397     data.resize(max(pixelMap->GetByteCount(), MIN_COMPRESS_BUF_SIZE));
398 
399     MediaLibraryTracer tracer;
400     tracer.Start("imagePacker.StartPacking");
401     ImagePacker imagePacker;
402     uint32_t err = imagePacker.StartPacking(data.data(), data.size(), option);
403     tracer.Finish();
404     if (err != E_OK) {
405         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
406         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, static_cast<int32_t>(err)},
407             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
408         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
409         return false;
410     }
411 
412     tracer.Start("imagePacker.AddImage");
413     err = imagePacker.AddImage(*pixelMap);
414     tracer.Finish();
415     if (err != E_OK) {
416         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
417         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, static_cast<int32_t>(err)},
418             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
419         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
420         return false;
421     }
422 
423     tracer.Start("imagePacker.FinalizePacking");
424     int64_t packedSize = 0;
425     err = imagePacker.FinalizePacking(packedSize);
426     if (err != E_OK) {
427         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
428         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, static_cast<int32_t>(err)},
429             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
430         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
431         return false;
432     }
433 
434     data.resize(packedSize);
435     return true;
436 }
437 
QueryThumbnailSet(ThumbRdbOpt & opts)438 shared_ptr<ResultSet> ThumbnailUtils::QueryThumbnailSet(ThumbRdbOpt &opts)
439 {
440     vector<string> column = {
441         MEDIA_DATA_DB_ID,
442         MEDIA_DATA_DB_FILE_PATH,
443         MEDIA_DATA_DB_MEDIA_TYPE,
444     };
445 
446     vector<string> selectionArgs;
447     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + opts.row;
448 
449     RdbPredicates rdbPredicates(opts.table);
450     rdbPredicates.SetWhereClause(strQueryCondition);
451     rdbPredicates.SetWhereArgs(selectionArgs);
452     return opts.store->QueryByStep(rdbPredicates, column);
453 }
454 
QueryThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)455 shared_ptr<ResultSet> ThumbnailUtils::QueryThumbnailInfo(ThumbRdbOpt &opts,
456     ThumbnailData &data, int &err)
457 {
458     MediaLibraryTracer tracer;
459     tracer.Start("QueryThumbnailInfo");
460     auto resultSet = QueryThumbnailSet(opts);
461     if (!CheckResultSetCount(resultSet, err)) {
462         return nullptr;
463     }
464 
465     err = resultSet->GoToFirstRow();
466     if (err != E_OK) {
467         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
468             {KEY_OPT_TYPE, OptType::THUMB}};
469         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
470         return nullptr;
471     }
472 
473     ParseQueryResult(resultSet, data, err);
474     return resultSet;
475 }
476 
QueryLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)477 bool ThumbnailUtils::QueryLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
478 {
479     vector<string> column = {
480         MEDIA_DATA_DB_ID,
481     };
482     RdbPredicates rdbPredicates(opts.table);
483     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
484         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
485     }
486     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
487     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
488     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
489     if (resultSet == nullptr) {
490         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
491             {KEY_OPT_TYPE, OptType::THUMB}};
492         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
493         return false;
494     }
495     int rowCount = 0;
496     err = resultSet->GetRowCount(rowCount);
497     resultSet.reset();
498     if (err != E_OK) {
499         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
500         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
501             {KEY_OPT_TYPE, OptType::THUMB}};
502         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
503         return false;
504     }
505     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
506     if (rowCount <= 0) {
507         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
508         rowCount = 0;
509     }
510 
511     outLcdCount = rowCount;
512     return true;
513 }
514 
QueryLcdCountByTime(const int64_t & time,const bool & before,ThumbRdbOpt & opts,int & outLcdCount,int & err)515 bool ThumbnailUtils::QueryLcdCountByTime(const int64_t &time, const bool &before, ThumbRdbOpt &opts, int &outLcdCount,
516     int &err)
517 {
518     vector<string> column = {
519         MEDIA_DATA_DB_ID,
520     };
521     RdbPredicates rdbPredicates(opts.table);
522     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
523         if (before) {
524             rdbPredicates.LessThanOrEqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
525         } else {
526             rdbPredicates.GreaterThan(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
527         }
528     }
529     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
530     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
531     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
532     if (resultSet == nullptr) {
533         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
534             {KEY_OPT_TYPE, OptType::THUMB}};
535         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
536         return false;
537     }
538     int rowCount = 0;
539     err = resultSet->GetRowCount(rowCount);
540     resultSet.reset();
541     if (err != E_OK) {
542         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
543         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
544             {KEY_OPT_TYPE, OptType::THUMB}};
545         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
546         return false;
547     }
548     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
549     if (rowCount <= 0) {
550         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
551         rowCount = 0;
552     }
553 
554     outLcdCount = rowCount;
555     return true;
556 }
557 
QueryDistributeLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)558 bool ThumbnailUtils::QueryDistributeLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
559 {
560     vector<string> column = {
561         REMOTE_THUMBNAIL_DB_ID,
562     };
563     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
564     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
565     rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
566     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
567     if (resultSet == nullptr) {
568         return false;
569     }
570     int rowCount = 0;
571     err = resultSet->GetRowCount(rowCount);
572     resultSet.reset();
573     if (err != E_OK) {
574         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
575         return false;
576     }
577     MEDIA_INFO_LOG("rowCount is %{public}d", rowCount);
578     if (rowCount <= 0) {
579         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
580         rowCount = 0;
581     }
582     outLcdCount = rowCount;
583     return true;
584 }
585 
586 #ifdef DISTRIBUTED
QueryAgingDistributeLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailData> & infos,int & err)587 bool ThumbnailUtils::QueryAgingDistributeLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
588     vector<ThumbnailData> &infos, int &err)
589 {
590     vector<string> column = {
591         REMOTE_THUMBNAIL_DB_FILE_ID,
592         MEDIA_DATA_DB_LCD
593     };
594     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
595     rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
596     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
597 
598     rdbPredicates.Limit(LcdLimit);
599     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
600     if (!CheckResultSetCount(resultSet, err)) {
601         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
602         return false;
603     }
604 
605     err = resultSet->GoToFirstRow();
606     if (err != E_OK) {
607         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
608         return false;
609     }
610 
611     ThumbnailData data;
612     do {
613         ParseQueryResult(resultSet, data, err);
614         if (!data.lcdKey.empty()) {
615             infos.push_back(data);
616         }
617     } while (resultSet->GoToNextRow() == E_OK);
618     return true;
619 }
620 #endif
621 
QueryAgingLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailData> & infos,int & err)622 bool ThumbnailUtils::QueryAgingLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
623     vector<ThumbnailData> &infos, int &err)
624 {
625     vector<string> column = {
626         MEDIA_DATA_DB_ID,
627         MEDIA_DATA_DB_FILE_PATH,
628         MEDIA_DATA_DB_MEDIA_TYPE,
629     };
630     RdbPredicates rdbPredicates(opts.table);
631     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
632     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
633 
634     rdbPredicates.Limit(LcdLimit);
635     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
636         rdbPredicates.OrderByAsc(PhotoColumn::PHOTO_LAST_VISIT_TIME);
637     }
638     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
639     if (!CheckResultSetCount(resultSet, err)) {
640         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
641         return false;
642     }
643 
644     err = resultSet->GoToFirstRow();
645     if (err != E_OK) {
646         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
647         return false;
648     }
649 
650     ThumbnailData data;
651     do {
652         ParseQueryResult(resultSet, data, err);
653         if (!data.path.empty()) {
654             infos.push_back(data);
655         }
656     } while (resultSet->GoToNextRow() == E_OK);
657     return true;
658 }
659 
QueryNoLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailData> & infos,int & err)660 bool ThumbnailUtils::QueryNoLcdInfos(ThumbRdbOpt &opts, int LcdLimit, vector<ThumbnailData> &infos, int &err)
661 {
662     vector<string> column = {
663         MEDIA_DATA_DB_ID,
664         MEDIA_DATA_DB_FILE_PATH,
665         MEDIA_DATA_DB_MEDIA_TYPE,
666     };
667     RdbPredicates rdbPredicates(opts.table);
668     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
669         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
670     }
671     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
672     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
673     if ((opts.table == PhotoColumn::PHOTOS_TABLE) || (opts.table == AudioColumn::AUDIOS_TABLE)) {
674         rdbPredicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, "0");
675     } else {
676         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
677     }
678     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
679     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
680         // Filter data that Only exists in Cloud to avoid cosuming data of downloading the original image
681         // meaning of Position: 1--only in local, 2--only in cloud, 3--both in local and cloud
682         rdbPredicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->
683             EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
684     }
685 
686     rdbPredicates.Limit(LcdLimit);
687     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
688     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
689     if (!CheckResultSetCount(resultSet, err)) {
690         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
691         return false;
692     }
693 
694     err = resultSet->GoToFirstRow();
695     if (err != E_OK) {
696         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
697         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
698             {KEY_OPT_TYPE, OptType::THUMB}};
699         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
700         return false;
701     }
702 
703     ThumbnailData data;
704     do {
705         ParseQueryResult(resultSet, data, err);
706         if (!data.path.empty()) {
707             infos.push_back(data);
708         }
709     } while (resultSet->GoToNextRow() == E_OK);
710     return true;
711 }
712 
QueryNoThumbnailInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)713 bool ThumbnailUtils::QueryNoThumbnailInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
714 {
715     vector<string> column = {
716         MEDIA_DATA_DB_ID,
717         MEDIA_DATA_DB_FILE_PATH,
718         MEDIA_DATA_DB_MEDIA_TYPE,
719     };
720     RdbPredicates rdbPredicates(opts.table);
721     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
722         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
723     }
724     if ((opts.table == PhotoColumn::PHOTOS_TABLE) || (opts.table == AudioColumn::AUDIOS_TABLE)) {
725         rdbPredicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, "0");
726     } else {
727         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
728     }
729     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
730     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
731     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
732     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
733         // Filter data that Only exists in Cloud to avoid cosuming data of downloading the original image
734         // meaning of Position: 1--only in local, 2--only in cloud, 3--both in local and cloud
735         rdbPredicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->
736             EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
737     }
738 
739     rdbPredicates.Limit(THUMBNAIL_QUERY_MAX);
740     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
741 
742     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
743     if (!CheckResultSetCount(resultSet, err)) {
744         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
745         if (err == E_EMPTY_VALUES_BUCKET) {
746             return true;
747         }
748         return false;
749     }
750 
751     err = resultSet->GoToFirstRow();
752     if (err != E_OK) {
753         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
754         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
755             {KEY_OPT_TYPE, OptType::THUMB}};
756         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
757         return false;
758     }
759 
760     ThumbnailData data;
761     do {
762         ParseQueryResult(resultSet, data, err);
763         if (!data.path.empty()) {
764             infos.push_back(data);
765         }
766     } while (resultSet->GoToNextRow() == E_OK);
767     return true;
768 }
769 
QueryNoAstcInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)770 bool ThumbnailUtils::QueryNoAstcInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
771 {
772     vector<string> column = {
773         MEDIA_DATA_DB_ID,
774         MEDIA_DATA_DB_FILE_PATH,
775         MEDIA_DATA_DB_MEDIA_TYPE,
776         MEDIA_DATA_DB_DATE_ADDED,
777         MEDIA_DATA_DB_NAME,
778     };
779     RdbPredicates rdbPredicates(opts.table);
780     rdbPredicates.EqualTo(PhotoColumn::PHOTO_HAS_ASTC, "0");
781     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
782     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
783     if (!CheckResultSetCount(resultSet, err)) {
784         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
785         if (err == E_EMPTY_VALUES_BUCKET) {
786             return true;
787         }
788         return false;
789     }
790 
791     err = resultSet->GoToFirstRow();
792     if (err != E_OK) {
793         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
794         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
795             {KEY_OPT_TYPE, OptType::THUMB}};
796         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
797         return false;
798     }
799 
800     ThumbnailData data;
801     do {
802         ParseQueryResult(resultSet, data, err);
803         if (!data.path.empty()) {
804             infos.push_back(data);
805         }
806     } while (resultSet->GoToNextRow() == E_OK);
807     return true;
808 }
809 
QueryNewThumbnailCount(ThumbRdbOpt & opts,const int64_t & time,int & count,int & err)810 bool ThumbnailUtils::QueryNewThumbnailCount(ThumbRdbOpt &opts, const int64_t &time, int &count,
811     int &err)
812 {
813     vector<string> column = {
814         MEDIA_DATA_DB_ID,
815     };
816     RdbPredicates rdbPredicates(opts.table);
817     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
818         rdbPredicates.GreaterThan(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
819     }
820     if (opts.table == MEDIALIBRARY_TABLE) {
821         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
822     } else {
823         rdbPredicates.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
824     }
825     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
826     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
827     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
828 
829     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
830 
831     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
832     if (resultSet == nullptr) {
833         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
834             {KEY_OPT_TYPE, OptType::THUMB}};
835         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
836         return false;
837     }
838     int rowCount = 0;
839     err = resultSet->GetRowCount(rowCount);
840     resultSet.reset();
841     if (err != E_OK) {
842         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
843         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
844             {KEY_OPT_TYPE, OptType::THUMB}};
845         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
846         return false;
847     }
848     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
849     if (rowCount <= 0) {
850         MEDIA_INFO_LOG("No match! %{public}s", rdbPredicates.ToString().c_str());
851         rowCount = 0;
852     }
853 
854     count = rowCount;
855     return true;
856 }
857 
UpdateLcdInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)858 bool ThumbnailUtils::UpdateLcdInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
859 {
860     ValuesBucket values;
861     int changedRows;
862 
863     MediaLibraryTracer tracer;
864     tracer.Start("UpdateLcdInfo opts.store->Update");
865     int64_t timeNow = UTCTimeMilliSeconds();
866     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, timeNow);
867     err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
868         vector<string> { opts.row });
869     if (err != NativeRdb::E_OK) {
870         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
871         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
872             {KEY_OPT_TYPE, OptType::THUMB}};
873         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
874         return false;
875     }
876     return true;
877 }
878 
UpdateVisitTime(ThumbRdbOpt & opts,ThumbnailData & data,int & err)879 bool ThumbnailUtils::UpdateVisitTime(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
880 {
881 #ifdef DISTRIBUTED
882     if (!opts.networkId.empty()) {
883         return DoUpdateRemoteThumbnail(opts, data, err);
884     }
885 #endif
886 
887     ValuesBucket values;
888     int changedRows;
889     int64_t timeNow = UTCTimeMilliSeconds();
890     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, timeNow);
891     err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
892         vector<string> { opts.row });
893     if (err != NativeRdb::E_OK) {
894         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
895         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
896             {KEY_OPT_TYPE, OptType::THUMB}};
897         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
898         return false;
899     }
900     return true;
901 }
902 
903 #ifdef DISTRIBUTED
QueryDeviceThumbnailRecords(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)904 bool ThumbnailUtils::QueryDeviceThumbnailRecords(ThumbRdbOpt &opts, vector<ThumbnailData> &infos,
905     int &err)
906 {
907     vector<string> column = {
908         REMOTE_THUMBNAIL_DB_FILE_ID,
909         MEDIA_DATA_DB_THUMBNAIL,
910         MEDIA_DATA_DB_LCD
911     };
912     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
913     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
914     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
915     if (!CheckResultSetCount(resultSet, err)) {
916         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
917         return false;
918     }
919 
920     err = resultSet->GoToFirstRow();
921     if (err != E_OK) {
922         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
923         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
924             {KEY_OPT_TYPE, OptType::THUMB}};
925         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
926         return false;
927     }
928 
929     ThumbnailData data;
930     do {
931         ParseQueryResult(resultSet, data, err);
932         infos.push_back(data);
933     } while (resultSet->GoToNextRow() == E_OK);
934     return true;
935 }
936 
GetUdidByNetworkId(ThumbRdbOpt & opts,const string & networkId,string & outUdid,int & err)937 bool ThumbnailUtils::GetUdidByNetworkId(ThumbRdbOpt &opts, const string &networkId,
938     string &outUdid, int &err)
939 {
940     vector<string> column = {
941         DEVICE_DB_ID,
942         DEVICE_DB_UDID
943     };
944     RdbPredicates rdbPredicates(DEVICE_TABLE);
945     rdbPredicates.EqualTo(DEVICE_DB_NETWORK_ID, networkId);
946     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
947     if (!CheckResultSetCount(resultSet, err)) {
948         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
949         return false;
950     }
951 
952     err = resultSet->GoToFirstRow();
953     if (err != E_OK) {
954         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
955         return false;
956     }
957     int index;
958     err = resultSet->GetColumnIndex(DEVICE_DB_UDID, index);
959     if (err == NativeRdb::E_OK) {
960         ParseStringResult(resultSet, index, outUdid, err);
961     } else {
962         MEDIA_ERR_LOG("Get column index error %{public}d", err);
963     }
964     return true;
965 }
966 
QueryRemoteThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int & err)967 bool ThumbnailUtils::QueryRemoteThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
968 {
969     if (data.udid.empty() && !GetUdidByNetworkId(opts, opts.networkId, data.udid, err)) {
970         MEDIA_ERR_LOG("GetUdidByNetworkId failed! %{public}d", err);
971         return false;
972     }
973 
974     vector<string> column = {
975         REMOTE_THUMBNAIL_DB_ID,
976         MEDIA_DATA_DB_THUMBNAIL,
977         MEDIA_DATA_DB_LCD
978     };
979     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
980     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, data.id);
981     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, data.udid);
982     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
983     if (!CheckResultSetCount(resultSet, err)) {
984         MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
985         return false;
986     }
987 
988     err = resultSet->GoToFirstRow();
989     if (err != E_OK) {
990         MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
991         return false;
992     }
993 
994     int index;
995     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_LCD, index);
996     if (err == NativeRdb::E_OK) {
997         ParseStringResult(resultSet, index, data.lcdKey, err);
998     }
999 
1000     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_THUMBNAIL, index);
1001     if (err == NativeRdb::E_OK) {
1002         ParseStringResult(resultSet, index, data.thumbnailKey, err);
1003     }
1004     return true;
1005 }
1006 
IsKeyNotSame(const string & newKey,const string & oldKey)1007 static inline bool IsKeyNotSame(const string &newKey, const string &oldKey)
1008 {
1009     return !newKey.empty() && !oldKey.empty() && (newKey != oldKey);
1010 }
1011 
DoUpdateRemoteThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1012 bool ThumbnailUtils::DoUpdateRemoteThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1013 {
1014     if (opts.networkId.empty()) {
1015         return false;
1016     }
1017     if (data.thumbnailKey.empty() && data.lcdKey.empty()) {
1018         return false;
1019     }
1020     ThumbnailData tmpData = data;
1021     auto isGot = ThumbnailUtils::QueryRemoteThumbnail(opts, tmpData, err);
1022     if (isGot) {
1023         if (IsKeyNotSame(data.thumbnailKey, tmpData.thumbnailKey)) {
1024             if (!RemoveDataFromKv(opts.kvStore, tmpData.thumbnailKey)) {
1025                 return false;
1026             }
1027         }
1028         if (IsKeyNotSame(data.lcdKey, tmpData.lcdKey)) {
1029             if (!RemoveDataFromKv(opts.kvStore, tmpData.lcdKey)) {
1030                 return false;
1031             }
1032         }
1033     }
1034 
1035     data.udid = tmpData.udid;
1036     if (isGot) {
1037         return UpdateRemoteThumbnailInfo(opts, data, err);
1038     } else {
1039         return InsertRemoteThumbnailInfo(opts, data, err);
1040     }
1041 }
1042 
UpdateRemoteThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1043 bool ThumbnailUtils::UpdateRemoteThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1044 {
1045     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
1046     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, data.id);
1047     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, data.udid);
1048 
1049     ValuesBucket values;
1050     if (!data.thumbnailKey.empty()) {
1051         values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
1052     }
1053 
1054     if (!data.lcdKey.empty()) {
1055         values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
1056     }
1057 
1058     int changedRows;
1059     err = opts.store->Update(changedRows, values, rdbPredicates);
1060     if (err != NativeRdb::E_OK) {
1061         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1062         return false;
1063     }
1064 
1065     return true;
1066 }
1067 
InsertRemoteThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)1068 bool ThumbnailUtils::InsertRemoteThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
1069 {
1070     ValuesBucket values;
1071     values.PutInt(REMOTE_THUMBNAIL_DB_FILE_ID, stoi(data.id));
1072     values.PutString(REMOTE_THUMBNAIL_DB_UDID, data.udid);
1073     if (!data.thumbnailKey.empty()) {
1074         values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
1075     }
1076 
1077     if (!data.lcdKey.empty()) {
1078         values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
1079     }
1080 
1081     int64_t outRowId = -1;
1082     err = opts.store->Insert(outRowId, REMOTE_THUMBNAIL_TABLE, values);
1083     if (err != NativeRdb::E_OK) {
1084         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1085         return false;
1086     }
1087     return true;
1088 }
1089 #endif
1090 
CleanThumbnailInfo(ThumbRdbOpt & opts,bool withThumb,bool withLcd)1091 bool ThumbnailUtils::CleanThumbnailInfo(ThumbRdbOpt &opts, bool withThumb, bool withLcd)
1092 {
1093     ValuesBucket values;
1094     if (withThumb) {
1095         values.PutNull(MEDIA_DATA_DB_THUMBNAIL);
1096     }
1097     if (withLcd) {
1098         values.PutInt(MEDIA_DATA_DB_DIRTY, static_cast<int32_t>(DirtyType::TYPE_SYNCED));
1099         if (opts.table == MEDIALIBRARY_TABLE) {
1100             values.PutNull(MEDIA_DATA_DB_LCD);
1101         }
1102         if (opts.table == PhotoColumn::PHOTOS_TABLE) {
1103             values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, 0);
1104         }
1105     }
1106     int changedRows;
1107     auto err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1108         vector<string> { opts.row });
1109     if (err != NativeRdb::E_OK) {
1110         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
1111         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
1112             {KEY_OPT_TYPE, OptType::THUMB}};
1113         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1114         return false;
1115     }
1116     return true;
1117 }
1118 
1119 #ifdef DISTRIBUTED
CleanDistributeLcdInfo(ThumbRdbOpt & opts)1120 bool ThumbnailUtils::CleanDistributeLcdInfo(ThumbRdbOpt &opts)
1121 {
1122     string udid;
1123     int err;
1124     if (!GetUdidByNetworkId(opts, opts.networkId, udid, err)) {
1125         MEDIA_ERR_LOG("GetUdidByNetworkId failed! %{public}d", err);
1126         return false;
1127     }
1128 
1129     ValuesBucket values;
1130     values.PutNull(MEDIA_DATA_DB_LCD);
1131     int changedRows;
1132     vector<string> whereArgs = { udid, opts.row };
1133     string deleteCondition = REMOTE_THUMBNAIL_DB_UDID + " = ? AND " +
1134         REMOTE_THUMBNAIL_DB_FILE_ID + " = ?";
1135     auto ret = opts.store->Update(changedRows, REMOTE_THUMBNAIL_TABLE, values, deleteCondition, whereArgs);
1136     if (ret != NativeRdb::E_OK) {
1137         MEDIA_ERR_LOG("RdbStore Delete failed! %{public}d", ret);
1138         return false;
1139     }
1140     return true;
1141 }
1142 
DeleteDistributeThumbnailInfo(ThumbRdbOpt & opts)1143 bool ThumbnailUtils::DeleteDistributeThumbnailInfo(ThumbRdbOpt &opts)
1144 {
1145     int changedRows;
1146     vector<string> whereArgs = { opts.udid, opts.row };
1147     string deleteCondition = REMOTE_THUMBNAIL_DB_UDID + " = ? AND " +
1148         REMOTE_THUMBNAIL_DB_FILE_ID + " = ?";
1149     auto err = opts.store->Delete(changedRows, REMOTE_THUMBNAIL_TABLE, deleteCondition, whereArgs);
1150     if (err != NativeRdb::E_OK) {
1151         MEDIA_ERR_LOG("RdbStore Delete failed! %{public}d", err);
1152         return false;
1153     }
1154     return true;
1155 }
1156 #endif
1157 
ConvertDecodeSize(const Size & sourceSize,Size & desiredSize,const bool isThumbnail)1158 Size ThumbnailUtils::ConvertDecodeSize(const Size &sourceSize, Size &desiredSize, const bool isThumbnail)
1159 {
1160     int width = sourceSize.width;
1161     int height = sourceSize.height;
1162     if (isThumbnail) {
1163         if (!ResizeThumb(width, height)) {
1164             MEDIA_ERR_LOG("ResizeThumb failed");
1165         }
1166         desiredSize = {width, height};
1167         float desiredScale = static_cast<float>(desiredSize.height) / static_cast<float>(desiredSize.width);
1168         float sourceScale = static_cast<float>(sourceSize.height) / static_cast<float>(sourceSize.width);
1169         float scale = 1.0f;
1170         if ((sourceScale - desiredScale > EPSILON) ^ isThumbnail) {
1171             scale = (float)desiredSize.height / sourceSize.height;
1172         } else {
1173             scale = (float)desiredSize.width / sourceSize.width;
1174         }
1175         scale = scale < 1.0f ? scale : 1.0f;
1176         Size decodeSize = {
1177             static_cast<int32_t> (scale * sourceSize.width),
1178             static_cast<int32_t> (scale * sourceSize.height),
1179         };
1180         return decodeSize;
1181     } else {
1182         if (!ResizeLcd(width, height)) {
1183             MEDIA_ERR_LOG("ResizeThumb failed");
1184         }
1185         desiredSize = {width, height};
1186         return desiredSize.width != 0 && desiredSize.height != 0 ? desiredSize : sourceSize;
1187     }
1188 }
1189 
LoadSourceImage(ThumbnailData & data,const bool isThumbnail,const std::string & targetPath)1190 bool ThumbnailUtils::LoadSourceImage(ThumbnailData &data, const bool isThumbnail, const std::string &targetPath)
1191 {
1192     if (data.source != nullptr) {
1193         return true;
1194     }
1195     MediaLibraryTracer tracer;
1196     tracer.Start("LoadSourceImage");
1197     if (data.mediaType == -1) {
1198         auto extension = MediaFileUtils::GetExtensionFromPath(data.path);
1199         auto mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension);
1200         data.mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1201     }
1202 
1203     bool ret = false;
1204     data.degrees = 0.0;
1205     Size desiredSize;
1206     bool isThumbnailExist = !targetPath.empty();
1207     if (data.mediaType == MEDIA_TYPE_VIDEO && !isThumbnailExist) {
1208         ret = LoadVideoFile(data, isThumbnail, desiredSize);
1209     } else if (data.mediaType == MEDIA_TYPE_AUDIO && !isThumbnailExist) {
1210         ret = LoadAudioFile(data, isThumbnail, desiredSize);
1211     } else {
1212         ret = LoadImageFile(data, isThumbnail, desiredSize, targetPath);
1213     }
1214     if (!ret || (data.source == nullptr)) {
1215         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
1216             {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
1217         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1218         return false;
1219     }
1220     tracer.Finish();
1221 
1222     if (isThumbnail && !isThumbnailExist) {
1223         tracer.Start("CenterScale");
1224         PostProc postProc;
1225         if (!postProc.CenterScale(desiredSize, *data.source)) {
1226             MEDIA_ERR_LOG("thumbnail center crop failed [%{private}s]", data.id.c_str());
1227             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
1228                 {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
1229             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1230             return false;
1231         }
1232     }
1233     data.source->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
1234     data.source->rotate(data.degrees);
1235     return true;
1236 }
1237 
ScaleFastThumb(ThumbnailData & data,const Size & size)1238 bool ThumbnailUtils::ScaleFastThumb(ThumbnailData &data, const Size &size)
1239 {
1240     MediaLibraryTracer tracer;
1241     tracer.Start("ScaleFastThumb");
1242 
1243     PostProc postProc;
1244     if (!postProc.CenterScale(size, *data.source)) {
1245         MEDIA_ERR_LOG("thumbnail center crop failed [%{private}s]", data.id.c_str());
1246         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_UNKNOWN},
1247             {KEY_OPT_FILE, data.path}, {KEY_OPT_TYPE, OptType::THUMB}};
1248         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1249         return false;
1250     }
1251     return true;
1252 }
1253 
Desensitize(string & str)1254 static string Desensitize(string &str)
1255 {
1256     string result = str;
1257     auto index = result.find('/');
1258     if (index == string::npos) {
1259         return "*****";
1260     }
1261 
1262     result.replace(0, index, index, '*');
1263     return result;
1264 }
1265 
SaveFile(const string & fileName,uint8_t * output,int writeSize)1266 static int SaveFile(const string &fileName, uint8_t *output, int writeSize)
1267 {
1268     string tempFileName = fileName + ".tmp";
1269     const mode_t fileMode = 0664;
1270     mode_t mask = umask(0);
1271     UniqueFd fd(open(tempFileName.c_str(), O_WRONLY | O_CREAT | O_TRUNC, fileMode));
1272     umask(mask);
1273     if (fd.Get() < 0) {
1274         if (errno == EEXIST) {
1275             UniqueFd fd(open(tempFileName.c_str(), O_WRONLY | O_TRUNC, fileMode));
1276         }
1277         if (fd.Get() < 0) {
1278             string dir = MediaFileUtils::GetParentPath(tempFileName);
1279             if (access(dir.c_str(), F_OK) != 0) {
1280                 string dirToPrint = Desensitize(dir);
1281                 MEDIA_ERR_LOG("parent path does not exist, path %{public}s", dirToPrint.c_str());
1282             }
1283             string fileNameToPrint = Desensitize(tempFileName);
1284             MEDIA_ERR_LOG("save failed! filePath %{pulibc}s status %{public}d", fileNameToPrint.c_str(), errno);
1285             return -errno;
1286         }
1287     }
1288     int ret = write(fd.Get(), output, writeSize);
1289     if (ret < 0) {
1290         MEDIA_ERR_LOG("write failed errno %{public}d", errno);
1291         return -errno;
1292     }
1293     int32_t errCode = fsync(fd.Get());
1294     if (errCode < 0) {
1295         MEDIA_ERR_LOG("fsync failed errno %{public}d", errno);
1296         return -errno;
1297     }
1298     close(fd.Release());
1299 
1300     if (MediaFileUtils::IsFileExists(fileName)) {
1301         if (!MediaFileUtils::DeleteFile(fileName)) {
1302             return -errno;
1303         }
1304     }
1305     errCode = MediaFileUtils::ModifyAsset(tempFileName, fileName);
1306     if (errCode != E_OK) {
1307         int32_t lastErrno = errno;
1308         if (!MediaFileUtils::DeleteFile(tempFileName)) {
1309             MEDIA_WARN_LOG("Delete tmp thumb error: %{public}d, name: %{private}s", errno, tempFileName.c_str());
1310         }
1311         if (errCode == E_FILE_EXIST || (errCode == E_FILE_OPER_FAIL && lastErrno == EEXIST)) {
1312             return E_OK;
1313         }
1314         return errCode;
1315     }
1316     return ret;
1317 }
1318 
SaveFileCreateDir(const string & path,const string & suffix,string & fileName)1319 int ThumbnailUtils::SaveFileCreateDir(const string &path, const string &suffix, string &fileName)
1320 {
1321     fileName = GetThumbnailPath(path, suffix);
1322     string dir = MediaFileUtils::GetParentPath(fileName);
1323     if (!MediaFileUtils::CreateDirectory(dir)) {
1324         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, -errno},
1325             {KEY_OPT_FILE, dir}, {KEY_OPT_TYPE, OptType::THUMB}};
1326         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1327         return -errno;
1328     }
1329     return E_OK;
1330 }
1331 
ToSaveFile(ThumbnailData & data,const ThumbnailType & type,const string & fileName,uint8_t * output,const int & writeSize)1332 int ThumbnailUtils::ToSaveFile(ThumbnailData &data, const ThumbnailType &type, const string &fileName,
1333     uint8_t *output, const int &writeSize)
1334 {
1335     int ret = SaveFile(fileName, output, writeSize);
1336     if (ret < 0) {
1337         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
1338             {KEY_OPT_FILE, fileName}, {KEY_OPT_TYPE, OptType::THUMB}};
1339         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1340         return ret;
1341     } else if (ret != writeSize) {
1342         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_NO_SPACE},
1343             {KEY_OPT_FILE, fileName}, {KEY_OPT_TYPE, OptType::THUMB}};
1344         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1345         return E_NO_SPACE;
1346     }
1347     return E_OK;
1348 }
1349 
TrySaveFile(ThumbnailData & data,ThumbnailType type)1350 int ThumbnailUtils::TrySaveFile(ThumbnailData &data, ThumbnailType type)
1351 {
1352     string suffix;
1353     uint8_t *output;
1354     int writeSize;
1355     switch (type) {
1356         case ThumbnailType::THUMB:
1357             suffix = THUMBNAIL_THUMB_SUFFIX;
1358             output = data.thumbnail.data();
1359             writeSize = data.thumbnail.size();
1360             break;
1361         case ThumbnailType::THUMB_ASTC:
1362             suffix = THUMBNAIL_THUMBASTC_SUFFIX;
1363             output = data.thumbAstc.data();
1364             writeSize = data.thumbAstc.size();
1365             break;
1366         case ThumbnailType::LCD:
1367             suffix = THUMBNAIL_LCD_SUFFIX;
1368             output = data.lcd.data();
1369             writeSize = data.lcd.size();
1370             break;
1371         case ThumbnailType::MTH_ASTC:
1372             output = data.monthAstc.data();
1373             writeSize = data.monthAstc.size();
1374             break;
1375         case ThumbnailType::YEAR_ASTC:
1376             output = data.yearAstc.data();
1377             writeSize = data.yearAstc.size();
1378             break;
1379         default:
1380             return E_INVALID_ARGUMENTS;
1381     }
1382     if (writeSize <= 0) {
1383         return E_THUMBNAIL_LOCAL_CREATE_FAIL;
1384     }
1385     if (type == ThumbnailType::MTH_ASTC || type == ThumbnailType::YEAR_ASTC) {
1386         return SaveAstcDataToKvStore(data, type);
1387     }
1388     return SaveThumbDataToLocalDir(data, type, suffix, output, writeSize);
1389 }
1390 
SaveThumbDataToLocalDir(ThumbnailData & data,const ThumbnailType & type,const std::string & suffix,uint8_t * output,const int writeSize)1391 int ThumbnailUtils::SaveThumbDataToLocalDir(ThumbnailData &data,
1392     const ThumbnailType &type, const std::string &suffix, uint8_t *output, const int writeSize)
1393 {
1394     string fileName;
1395     int ret = SaveFileCreateDir(data.path, suffix, fileName);
1396     if (ret != E_OK) {
1397         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
1398             {KEY_OPT_FILE, fileName}, {KEY_OPT_TYPE, OptType::THUMB}};
1399         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1400         MEDIA_ERR_LOG("SaveThumbDataToLocalDir create dir path %{public}s err %{public}d", data.path.c_str(), ret);
1401         return ret;
1402     }
1403     ret = ToSaveFile(data, type, fileName, output, writeSize);
1404     if (ret < 0) {
1405         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
1406             {KEY_OPT_FILE, fileName}, {KEY_OPT_TYPE, OptType::THUMB}};
1407         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1408         MEDIA_ERR_LOG("SaveThumbDataToLocalDir ToSaveFile path %{public}s err %{public}d", data.path.c_str(), ret);
1409         return ret;
1410     }
1411     return E_OK;
1412 }
1413 
SetSource(shared_ptr<AVMetadataHelper> avMetadataHelper,const string & path)1414 int32_t ThumbnailUtils::SetSource(shared_ptr<AVMetadataHelper> avMetadataHelper, const string &path)
1415 {
1416     if (avMetadataHelper == nullptr) {
1417         MEDIA_ERR_LOG("avMetadataHelper == nullptr");
1418         return E_ERR;
1419     }
1420     MEDIA_DEBUG_LOG("path = %{private}s", path.c_str());
1421     int32_t fd = open(path.c_str(), O_RDONLY);
1422     if (fd < 0) {
1423         MEDIA_ERR_LOG("Open file failed, err %{public}d", errno);
1424         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, -errno},
1425             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
1426         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1427         return E_ERR;
1428     }
1429 
1430     struct stat64 st;
1431     if (fstat64(fd, &st) != 0) {
1432         MEDIA_ERR_LOG("Get file state failed, err %{public}d", errno);
1433         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, -errno},
1434             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
1435         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1436         (void)close(fd);
1437         return E_ERR;
1438     }
1439     int64_t length = static_cast<int64_t>(st.st_size);
1440     int32_t ret = avMetadataHelper->SetSource(fd, 0, length, AV_META_USAGE_PIXEL_MAP);
1441     if (ret != 0) {
1442         MEDIA_ERR_LOG("SetSource fail");
1443         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
1444             {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
1445         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1446         (void)close(fd);
1447         return E_ERR;
1448     }
1449     (void)close(fd);
1450     return SUCCESS;
1451 }
1452 
ResizeImage(const vector<uint8_t> & data,const Size & size,unique_ptr<PixelMap> & pixelMap)1453 bool ThumbnailUtils::ResizeImage(const vector<uint8_t> &data, const Size &size, unique_ptr<PixelMap> &pixelMap)
1454 {
1455     MediaLibraryTracer tracer;
1456     tracer.Start("ResizeImage");
1457     if (data.size() == 0) {
1458         MEDIA_ERR_LOG("Data is empty");
1459         return false;
1460     }
1461 
1462     tracer.Start("ImageSource::CreateImageSource");
1463     uint32_t err = E_OK;
1464     SourceOptions opts;
1465     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(data.data(),
1466         data.size(), opts, err);
1467     if (err != E_OK) {
1468         MEDIA_ERR_LOG("Failed to create image source %{public}d", err);
1469         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, static_cast<int32_t>(err)},
1470             {KEY_OPT_FILE, ""}, {KEY_OPT_TYPE, OptType::THUMB}};
1471         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1472         return false;
1473     }
1474     tracer.Finish();
1475 
1476     tracer.Start("imageSource->CreatePixelMap");
1477     DecodeOptions decodeOpts;
1478     decodeOpts.desiredSize.width = size.width;
1479     decodeOpts.desiredSize.height = size.height;
1480     decodeOpts.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
1481     pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
1482     if (err != Media::SUCCESS) {
1483         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, static_cast<int32_t>(err)},
1484             {KEY_OPT_FILE, ""}, {KEY_OPT_TYPE, OptType::THUMB}};
1485         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
1486         MEDIA_ERR_LOG("Failed to create pixelmap %{public}d", err);
1487         return false;
1488     }
1489 
1490     return true;
1491 }
1492 
1493 #ifdef DISTRIBUTED
RemoveDataFromKv(const shared_ptr<SingleKvStore> & kvStore,const string & key)1494 bool ThumbnailUtils::RemoveDataFromKv(const shared_ptr<SingleKvStore> &kvStore, const string &key)
1495 {
1496     if (key.empty()) {
1497         MEDIA_ERR_LOG("RemoveLcdFromKv key empty");
1498         return false;
1499     }
1500 
1501     if (kvStore == nullptr) {
1502         MEDIA_ERR_LOG("KvStore is not init");
1503         return false;
1504     }
1505 
1506     MediaLibraryTracer tracer;
1507     tracer.Start("RemoveLcdFromKv kvStore->Get");
1508     auto status = kvStore->Delete(key);
1509     if (status != Status::SUCCESS) {
1510         MEDIA_ERR_LOG("Failed to get key [%{private}s] ret [%{private}d]", key.c_str(), status);
1511         return false;
1512     }
1513     return true;
1514 }
1515 #endif
1516 
1517 // notice: return value is whether thumb/lcd is deleted
DeleteOriginImage(ThumbRdbOpt & opts)1518 bool ThumbnailUtils::DeleteOriginImage(ThumbRdbOpt &opts)
1519 {
1520     ThumbnailData tmpData;
1521     tmpData.path = opts.path;
1522     bool isDelete = false;
1523     if (opts.path.empty()) {
1524         int err = 0;
1525         auto rdbSet = QueryThumbnailInfo(opts, tmpData, err);
1526         if (rdbSet == nullptr) {
1527             MEDIA_ERR_LOG("QueryThumbnailInfo Faild [ %{public}d ]", err);
1528             return isDelete;
1529         }
1530     }
1531     if (DeleteThumbFile(tmpData, ThumbnailType::YEAR)) {
1532         isDelete = true;
1533     }
1534     if (DeleteThumbFile(tmpData, ThumbnailType::MTH)) {
1535         isDelete = true;
1536     }
1537     if (DeleteThumbFile(tmpData, ThumbnailType::THUMB)) {
1538         isDelete = true;
1539     }
1540     if (ThumbnailUtils::IsSupportGenAstc()) {
1541         if (DeleteThumbFile(tmpData, ThumbnailType::THUMB_ASTC)) {
1542             isDelete = true;
1543         }
1544     }
1545     if (DeleteThumbFile(tmpData, ThumbnailType::LCD)) {
1546         isDelete = true;
1547     }
1548     string fileName = GetThumbnailPath(tmpData.path, "");
1549     return isDelete;
1550 }
1551 
1552 #ifdef DISTRIBUTED
IsImageExist(const string & key,const string & networkId,const shared_ptr<SingleKvStore> & kvStore)1553 bool ThumbnailUtils::IsImageExist(const string &key, const string &networkId, const shared_ptr<SingleKvStore> &kvStore)
1554 {
1555     if (key.empty()) {
1556         return false;
1557     }
1558 
1559     if (kvStore == nullptr) {
1560         MEDIA_ERR_LOG("KvStore is not init");
1561         return false;
1562     }
1563 
1564     bool ret = false;
1565     DataQuery query;
1566     query.InKeys({key});
1567     int count = 0;
1568     auto status = kvStore->GetCount(query, count);
1569     if (status == Status::SUCCESS && count > 0) {
1570         ret = true;
1571     }
1572 
1573     if (!ret) {
1574         if (!networkId.empty()) {
1575             MediaLibraryTracer tracer;
1576             tracer.Start("SyncPullKvstore");
1577             vector<string> keys = { key };
1578             auto syncStatus = MediaLibrarySyncOperation::SyncPullKvstore(kvStore, keys, networkId);
1579             if (syncStatus == DistributedKv::Status::SUCCESS) {
1580                 MEDIA_DEBUG_LOG("SyncPullKvstore SUCCESS");
1581                 return true;
1582             } else {
1583                 MEDIA_ERR_LOG("SyncPullKvstore failed! ret %{public}d", syncStatus);
1584                 return false;
1585             }
1586         }
1587     }
1588     return ret;
1589 }
1590 #endif
1591 
UTCTimeMilliSeconds()1592 int64_t ThumbnailUtils::UTCTimeMilliSeconds()
1593 {
1594     struct timespec t;
1595     constexpr int64_t SEC_TO_MSEC = 1e3;
1596     constexpr int64_t MSEC_TO_NSEC = 1e6;
1597     clock_gettime(CLOCK_REALTIME, &t);
1598     return t.tv_sec * SEC_TO_MSEC + t.tv_nsec / MSEC_TO_NSEC;
1599 }
1600 
CheckResultSetCount(const shared_ptr<ResultSet> & resultSet,int & err)1601 bool ThumbnailUtils::CheckResultSetCount(const shared_ptr<ResultSet> &resultSet, int &err)
1602 {
1603     if (resultSet == nullptr) {
1604         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
1605             {KEY_OPT_TYPE, OptType::THUMB}};
1606         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1607         return false;
1608     }
1609     int rowCount = 0;
1610     err = resultSet->GetRowCount(rowCount);
1611     if (err != E_OK) {
1612         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
1613         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
1614             {KEY_OPT_TYPE, OptType::THUMB}};
1615         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1616         return false;
1617     }
1618 
1619     if (rowCount <= 0) {
1620         MEDIA_ERR_LOG("CheckCount No match!");
1621         err = E_EMPTY_VALUES_BUCKET;
1622         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
1623             {KEY_OPT_TYPE, OptType::THUMB}};
1624         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1625         return false;
1626     }
1627 
1628     return true;
1629 }
1630 
ParseStringResult(const shared_ptr<ResultSet> & resultSet,int index,string & data,int & err)1631 void ThumbnailUtils::ParseStringResult(const shared_ptr<ResultSet> &resultSet, int index, string &data, int &err)
1632 {
1633     bool isNull = true;
1634     err = resultSet->IsColumnNull(index, isNull);
1635     if (err != E_OK) {
1636         MEDIA_ERR_LOG("Failed to check column %{public}d null %{public}d", index, err);
1637     }
1638 
1639     if (!isNull) {
1640         err = resultSet->GetString(index, data);
1641         if (err != E_OK) {
1642             MEDIA_ERR_LOG("Failed to get column %{public}d string %{public}d", index, err);
1643         }
1644     }
1645 }
1646 
ParseQueryResult(const shared_ptr<ResultSet> & resultSet,ThumbnailData & data,int & err)1647 void ThumbnailUtils::ParseQueryResult(const shared_ptr<ResultSet> &resultSet, ThumbnailData &data, int &err)
1648 {
1649     int index;
1650     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, index);
1651     if (err == NativeRdb::E_OK) {
1652         ParseStringResult(resultSet, index, data.id, err);
1653     }
1654 
1655     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_FILE_PATH, index);
1656     if (err == NativeRdb::E_OK) {
1657         ParseStringResult(resultSet, index, data.path, err);
1658     }
1659 
1660     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_ADDED, index);
1661     if (err == NativeRdb::E_OK) {
1662         ParseStringResult(resultSet, index, data.dateAdded, err);
1663     }
1664 
1665     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_NAME, index);
1666     if (err == NativeRdb::E_OK) {
1667         ParseStringResult(resultSet, index, data.displayName, err);
1668     }
1669 
1670     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_MEDIA_TYPE, index);
1671     if (err == NativeRdb::E_OK) {
1672         data.mediaType = MediaType::MEDIA_TYPE_ALL;
1673         err = resultSet->GetInt(index, data.mediaType);
1674     }
1675 }
1676 
ResizeThumb(int & width,int & height)1677 bool ThumbnailUtils::ResizeThumb(int &width, int &height)
1678 {
1679     int maxLen = max(width, height);
1680     int minLen = min(width, height);
1681     if (minLen == 0) {
1682         MEDIA_ERR_LOG("Divisor minLen is 0");
1683         return false;
1684     }
1685     double ratio = (double)maxLen / minLen;
1686     if (minLen > SHORT_SIDE_THRESHOLD) {
1687         minLen = SHORT_SIDE_THRESHOLD;
1688         maxLen = static_cast<int>(SHORT_SIDE_THRESHOLD * ratio);
1689         if (maxLen > MAXIMUM_SHORT_SIDE_THRESHOLD) {
1690             maxLen = MAXIMUM_SHORT_SIDE_THRESHOLD;
1691         }
1692         if (height > width) {
1693             width = minLen;
1694             height = maxLen;
1695         } else {
1696             width = maxLen;
1697             height = minLen;
1698         }
1699     } else if (minLen <= SHORT_SIDE_THRESHOLD && maxLen > SHORT_SIDE_THRESHOLD) {
1700         if (ratio > ASPECT_RATIO_THRESHOLD) {
1701             int newMaxLen = static_cast<int>(minLen * ASPECT_RATIO_THRESHOLD);
1702             if (height > width) {
1703                 width = minLen;
1704                 height = newMaxLen;
1705             } else {
1706                 width = newMaxLen;
1707                 height = minLen;
1708             }
1709         }
1710     }
1711     return true;
1712 }
1713 
ResizeLcd(int & width,int & height)1714 bool ThumbnailUtils::ResizeLcd(int &width, int &height)
1715 {
1716     int maxLen = max(width, height);
1717     int minLen = min(width, height);
1718     if (minLen == 0) {
1719         MEDIA_ERR_LOG("Divisor minLen is 0");
1720         return false;
1721     }
1722     double ratio = (double)maxLen / minLen;
1723     if (std::abs(ratio) < EPSILON) {
1724         MEDIA_ERR_LOG("ratio is 0");
1725         return false;
1726     }
1727     int newMaxLen = maxLen;
1728     int newMinLen = minLen;
1729     if (maxLen > LCD_LONG_SIDE_THRESHOLD) {
1730         newMaxLen = LCD_LONG_SIDE_THRESHOLD;
1731         newMinLen = static_cast<int>(newMaxLen / ratio);
1732     }
1733     int lastMinLen = newMinLen;
1734     int lastMaxLen = newMaxLen;
1735     if (newMinLen < LCD_SHORT_SIDE_THRESHOLD && minLen >= LCD_SHORT_SIDE_THRESHOLD) {
1736         lastMinLen = LCD_SHORT_SIDE_THRESHOLD;
1737         lastMaxLen = static_cast<int>(lastMinLen * ratio);
1738         if (lastMaxLen > MAXIMUM_LCD_LONG_SIDE) {
1739             lastMaxLen = MAXIMUM_LCD_LONG_SIDE;
1740             lastMinLen = static_cast<int>(lastMaxLen / ratio);
1741         }
1742     }
1743     if (height > width) {
1744         width = lastMinLen;
1745         height = lastMaxLen;
1746     } else {
1747         width = lastMaxLen;
1748         height = lastMinLen;
1749     }
1750     return true;
1751 }
1752 
IsSupportGenAstc()1753 bool ThumbnailUtils::IsSupportGenAstc()
1754 {
1755     return ImageSource::IsSupportGenAstc();
1756 }
1757 
SaveAstcDataToKvStore(ThumbnailData & data,const ThumbnailType & type)1758 int ThumbnailUtils::SaveAstcDataToKvStore(ThumbnailData &data, const ThumbnailType &type)
1759 {
1760     string key;
1761     if (!GenerateKvStoreKey(data.id, data.dateAdded, key)) {
1762         MEDIA_ERR_LOG("GenerateKvStoreKey failed");
1763         return E_ERR;
1764     }
1765 
1766     std::shared_ptr<MediaLibraryKvStore> kvStore;
1767     if (type == ThumbnailType::MTH_ASTC) {
1768         kvStore = MediaLibraryKvStoreManager::GetInstance()
1769             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
1770     } else if (type == ThumbnailType::YEAR_ASTC) {
1771         kvStore = MediaLibraryKvStoreManager::GetInstance()
1772             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
1773     } else {
1774         MEDIA_ERR_LOG("invalid thumbnailType");
1775         return E_ERR;
1776     }
1777     if (kvStore == nullptr) {
1778         MEDIA_ERR_LOG("kvStore is nullptr");
1779         return E_ERR;
1780     }
1781 
1782     std::vector<uint8_t> value;
1783     int status = kvStore->Query(key, value);
1784     data.isThumbAdded = status != E_OK;
1785 
1786     status = kvStore->Insert(key, type == ThumbnailType::MTH_ASTC ? data.monthAstc : data.yearAstc);
1787     MEDIA_INFO_LOG("type:%{public}d, field_id:%{public}s, status:%{public}d, isThumbAdded:%{public}d",
1788         type, key.c_str(), status, data.isThumbAdded);
1789     return status;
1790 }
1791 
GenerateKvStoreKey(const std::string & fieldId,const std::string & dateAdded,std::string & key)1792 bool ThumbnailUtils::GenerateKvStoreKey(const std::string &fieldId, const std::string &dateAdded, std::string &key)
1793 {
1794     if (fieldId.empty()) {
1795         MEDIA_ERR_LOG("fieldId is empty");
1796         return false;
1797     }
1798     if (dateAdded.empty()) {
1799         MEDIA_ERR_LOG("dateAdded is empty");
1800         return false;
1801     }
1802     if (dateAdded.length() < MAX_TIMEID_LENGTH) {
1803         MEDIA_ERR_LOG("dateAdded invalid");
1804         return false;
1805     }
1806 
1807     size_t length = fieldId.length();
1808     if (length >= MAX_FIELD_LENGTH) {
1809         MEDIA_ERR_LOG("fieldId too long");
1810         return false;
1811     }
1812     string assembledFieldId = KVSTORE_KEY_TEMPLATE.substr(length) + fieldId;
1813     key = dateAdded.substr(0, MAX_TIMEID_LENGTH) + assembledFieldId;
1814     return true;
1815 }
1816 
CheckDateAdded(ThumbRdbOpt & opts,ThumbnailData & data)1817 bool ThumbnailUtils::CheckDateAdded(ThumbRdbOpt &opts, ThumbnailData &data)
1818 {
1819     if (!data.dateAdded.empty()) {
1820         return true;
1821     }
1822 
1823     vector<string> column = {
1824         MEDIA_DATA_DB_DATE_ADDED,
1825     };
1826     vector<string> selectionArgs;
1827     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + data.id;
1828     RdbPredicates rdbPredicates(opts.table);
1829     rdbPredicates.SetWhereClause(strQueryCondition);
1830     rdbPredicates.SetWhereArgs(selectionArgs);
1831     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
1832 
1833     int err;
1834     if (!CheckResultSetCount(resultSet, err)) {
1835         MEDIA_ERR_LOG("CheckResultSetCount failed, err: %{public}d", err);
1836         return false;
1837     }
1838     err = resultSet->GoToFirstRow();
1839     if (err != E_OK) {
1840         MEDIA_ERR_LOG("GoToFirstRow failed, err: %{public}d", err);
1841         return false;
1842     }
1843 
1844     int index;
1845     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_ADDED, index);
1846     if (err == NativeRdb::E_OK) {
1847         ParseStringResult(resultSet, index, data.dateAdded, err);
1848     } else {
1849         MEDIA_ERR_LOG("GetColumnIndex failed, err: %{public}d", err);
1850         resultSet->Close();
1851         return false;
1852     }
1853     resultSet->Close();
1854     return true;
1855 }
1856 
QueryThumbnailDataFromFileId(ThumbRdbOpt & opts,const std::string & id,ThumbnailData & data,int & err)1857 void ThumbnailUtils::QueryThumbnailDataFromFileId(ThumbRdbOpt &opts, const std::string &id,
1858     ThumbnailData &data, int &err)
1859 {
1860     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1861     predicates.EqualTo(MediaColumn::MEDIA_ID, id);
1862     vector<string> columns = {
1863         MEDIA_DATA_DB_ID,
1864         MEDIA_DATA_DB_FILE_PATH,
1865         MEDIA_DATA_DB_MEDIA_TYPE,
1866         MEDIA_DATA_DB_DATE_ADDED,
1867     };
1868     auto resultSet = opts.store->QueryByStep(predicates, columns);
1869     if (resultSet == nullptr) {
1870         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
1871             {KEY_OPT_TYPE, OptType::THUMB}};
1872         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1873         return;
1874     }
1875     err = resultSet->GoToFirstRow();
1876     if (err != NativeRdb::E_OK) {
1877         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
1878             {KEY_OPT_TYPE, OptType::THUMB}};
1879         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1880         resultSet->Close();
1881         return;
1882     }
1883 
1884     ParseQueryResult(resultSet, data, err);
1885 
1886     int index;
1887     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_ADDED, index);
1888     if (err == NativeRdb::E_OK) {
1889         ParseStringResult(resultSet, index, data.dateAdded, err);
1890     }
1891 
1892     if (err != NativeRdb::E_OK || data.path.empty()) {
1893         MEDIA_ERR_LOG("Fail to query thumbnail data using id: %{public}s, err: %{public}d", id.c_str(), err);
1894         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
1895             {KEY_OPT_TYPE, OptType::THUMB}};
1896         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1897         resultSet->Close();
1898         return;
1899     }
1900     resultSet->Close();
1901 }
1902 
1903 } // namespace Media
1904 } // namespace OHOS
1905