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