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