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