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