• 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 #include "dfx_utils.h"
28 #include "directory_ex.h"
29 #include "distributed_kv_data_manager.h"
30 #include "exif_rotate_utils.h"
31 #include "hitrace_meter.h"
32 #include "image_packer.h"
33 #include "ipc_skeleton.h"
34 #include "iservice_registry.h"
35 #include "media_column.h"
36 #include "media_exif.h"
37 #include "media_remote_thumbnail_column.h"
38 #include "medialibrary_common_utils.h"
39 #include "medialibrary_errno.h"
40 #include "medialibrary_kvstore_manager.h"
41 #include "medialibrary_photo_operations.h"
42 #include "medialibrary_tracer.h"
43 #include "media_file_utils.h"
44 #include "media_log.h"
45 #include "mimetype_utils.h"
46 #include "parameter.h"
47 #include "post_proc.h"
48 #include "rdb_errno.h"
49 #include "result_set_utils.h"
50 #include "thumbnail_const.h"
51 #include "thumbnail_file_utils.h"
52 #include "thumbnail_image_framework_utils.h"
53 #include "thumbnail_rdb_utils.h"
54 #include "thumbnail_source_loading.h"
55 #include "unique_fd.h"
56 #include "wifi_device.h"
57 #include "post_event_utils.h"
58 #include "dfx_manager.h"
59 #include "image_format_convert.h"
60 #include "highlight_column.h"
61 
62 using namespace std;
63 using namespace OHOS::DistributedKv;
64 using namespace OHOS::NativeRdb;
65 
66 namespace OHOS {
67 namespace Media {
68 
69 static constexpr int STORAGE_MANAGER_MANAGER_ID = 5003;
70 static const std::string CLOUD_DATASHARE_URI = "datashareproxy://com.huawei.hmos.clouddrive/cloud_sp?Proxy=true";
71 
LoadAudioFileInfo(shared_ptr<AVMetadataHelper> avMetadataHelper,ThumbnailData & data,Size & desiredSize,uint32_t & errCode)72 bool ThumbnailUtils::LoadAudioFileInfo(shared_ptr<AVMetadataHelper> avMetadataHelper, ThumbnailData &data,
73     Size &desiredSize, uint32_t &errCode)
74 {
75     if (avMetadataHelper == nullptr || avMetadataHelper->FetchArtPicture() == nullptr) {
76         MEDIA_ERR_LOG("FetchArtPicture failed!");
77         return false;
78     }
79 
80     auto audioPicMemory = avMetadataHelper->FetchArtPicture();
81     SourceOptions opts;
82     unique_ptr<ImageSource> audioImageSource = ImageSource::CreateImageSource(audioPicMemory->GetBase(),
83         audioPicMemory->GetSize(), opts, errCode);
84     if (audioImageSource == nullptr) {
85         MEDIA_ERR_LOG("Failed to create image source! path %{public}s errCode %{public}d",
86             DfxUtils::GetSafePath(data.path).c_str(), errCode);
87         return false;
88     }
89 
90     ImageInfo imageInfo;
91     errCode = audioImageSource->GetImageInfo(0, imageInfo);
92     if (errCode != E_OK) {
93         MEDIA_ERR_LOG("Failed to get image info, path: %{public}s err: %{public}d",
94             DfxUtils::GetSafePath(data.path).c_str(), errCode);
95         return false;
96     }
97     data.stats.sourceWidth = imageInfo.size.width;
98     data.stats.sourceHeight = imageInfo.size.height;
99 
100     DecodeOptions decOpts;
101     decOpts.desiredSize = ConvertDecodeSize(data, imageInfo.size, desiredSize);
102     decOpts.desiredPixelFormat = PixelFormat::RGBA_8888;
103     auto pixelMapPtr = audioImageSource->CreatePixelMap(decOpts, errCode);
104     std::shared_ptr<PixelMap> pixelMap = std::move(pixelMapPtr);
105     if ((errCode != E_OK) || (pixelMap == nullptr)) {
106         MEDIA_ERR_LOG("Av meta data helper fetch frame at time failed");
107         if (errCode != E_OK) {
108             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
109                 {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, data.path},
110                 {KEY_OPT_TYPE, OptType::THUMB}};
111             PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
112         }
113         return false;
114     }
115     data.source.SetPixelMap(pixelMap);
116     return true;
117 }
118 
LoadAudioFile(ThumbnailData & data,Size & desiredSize)119 bool ThumbnailUtils::LoadAudioFile(ThumbnailData &data, Size &desiredSize)
120 {
121     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
122     string path = data.path;
123     int32_t err = SetSource(avMetadataHelper, path);
124     if (err != E_OK) {
125         MEDIA_ERR_LOG("Av meta data helper set source failed %{public}d", err);
126         return false;
127     }
128     uint32_t errCode = 0;
129     if (!LoadAudioFileInfo(avMetadataHelper, data, desiredSize, errCode)) {
130         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
131             {KEY_ERR_CODE, static_cast<int32_t>(errCode)}, {KEY_OPT_FILE, path}, {KEY_OPT_TYPE, OptType::THUMB}};
132         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
133         return false;
134     }
135     return true;
136 }
137 
LoadVideoFrame(ThumbnailData & data,Size & desiredSize,int64_t timeStamp)138 bool ThumbnailUtils::LoadVideoFrame(ThumbnailData &data, Size &desiredSize, int64_t timeStamp)
139 {
140     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
141     string path = data.path;
142     int32_t err = SetSource(avMetadataHelper, path);
143     if (err != 0) {
144         return false;
145     }
146     int32_t videoWidth = 0;
147     int32_t videoHeight = 0;
148     if (!ParseVideoSize(avMetadataHelper, videoWidth, videoHeight)) {
149         return false;
150     }
151     PixelMapParams param;
152     param.colorFormat = PixelFormat::RGBA_8888;
153     ConvertDecodeSize(data, {videoWidth, videoHeight}, desiredSize);
154     param.dstWidth = desiredSize.width;
155     param.dstHeight = desiredSize.height;
156     param.isSupportFlip = true;
157     int32_t queryOption = (timeStamp == AV_FRAME_TIME) ?
158         AVMetadataQueryOption::AV_META_QUERY_NEXT_SYNC : AVMetadataQueryOption::AV_META_QUERY_CLOSEST;
159 
160     std::shared_ptr<PixelMap> pixelMap = avMetadataHelper->FetchFrameYuv(timeStamp, queryOption, param);
161     if (pixelMap == nullptr) {
162         DfxManager::GetInstance()->HandleThumbnailError(path, DfxType::AV_FETCH_FRAME, err);
163         return false;
164     }
165     if (pixelMap->GetPixelFormat() == PixelFormat::YCBCR_P010) {
166         uint32_t ret = ImageFormatConvert::ConvertImageFormat(pixelMap, PixelFormat::RGBA_1010102);
167         CHECK_AND_RETURN_RET_LOG(ret == E_OK, false, "PixelMapYuv10ToRGBA_1010102: source ConvertImageFormat fail");
168     }
169 
170     data.source.SetPixelMap(pixelMap);
171     data.stats.sourceWidth = pixelMap->GetWidth();
172     data.stats.sourceHeight = pixelMap->GetHeight();
173     DfxManager::GetInstance()->HandleHighMemoryThumbnail(path, MEDIA_TYPE_VIDEO, videoWidth, videoHeight);
174     return true;
175 }
176 
ParseVideoSize(std::shared_ptr<AVMetadataHelper> & avMetadataHelper,int32_t & videoWidth,int32_t & videoHeight)177 bool ThumbnailUtils::ParseVideoSize(std::shared_ptr<AVMetadataHelper> &avMetadataHelper,
178     int32_t &videoWidth, int32_t &videoHeight)
179 {
180     auto resultMap = avMetadataHelper->ResolveMetadata();
181     CHECK_AND_RETURN_RET_LOG(!resultMap.empty(), false, "Map of video size is empty");
182     CHECK_AND_RETURN_RET_LOG(resultMap.count(AVMetadataCode::AV_KEY_VIDEO_ROTATE_ORIENTATION) != 0,
183         false, "Map does not have exif rotate");
184 
185     FlipAndRotateInfo info;
186     int32_t exifRotate = static_cast<int32_t>(ExifRotateType::TOP_LEFT);
187     std::string strOfExifRotate = resultMap.at(AVMetadataCode::AV_KEY_VIDEO_ROTATE_ORIENTATION);
188     CHECK_AND_RETURN_RET_LOG(strOfExifRotate.empty() || (ConvertStrToInt32(strOfExifRotate, exifRotate) &&
189         ExifRotateUtils::GetFlipAndRotateInfo(exifRotate, info)),
190         false, "Parse rotation from resultmap error");
191 
192     bool needRevolve = ((info.orientation + VERTICAL_ANGLE) % STRAIGHT_ANGLE != 0);
193     CHECK_AND_RETURN_RET_LOG(ConvertStrToInt32(resultMap.at(AVMetadataCode::AV_KEY_VIDEO_WIDTH),
194         needRevolve ? videoWidth : videoHeight), false, "Parse width from resultmap error");
195     CHECK_AND_RETURN_RET_LOG(ConvertStrToInt32(resultMap.at(AVMetadataCode::AV_KEY_VIDEO_HEIGHT),
196         needRevolve ? videoHeight : videoWidth), false, "Parse width from resultmap error");
197     return true;
198 }
199 
200 // gen pixelmap from data.souce.pixelMapSource, should ensure source is not null
GenTargetPixelmap(ThumbnailData & data,const Size & desiredSize)201 bool ThumbnailUtils::GenTargetPixelmap(ThumbnailData &data, const Size &desiredSize)
202 {
203     MediaLibraryTracer tracer;
204     tracer.Start("GenTargetPixelmap");
205     auto pixelMap = data.source.GetPixelMap();
206     if (pixelMap == nullptr) {
207         return false;
208     }
209 
210     if (!ScaleFastThumb(data, desiredSize)) {
211         return false;
212     }
213 
214     float widthScale = (1.0f * desiredSize.width) / pixelMap->GetWidth();
215     float heightScale = (1.0f * desiredSize.height) / pixelMap->GetHeight();
216     pixelMap->scale(widthScale, heightScale);
217     return true;
218 }
219 
ScaleTargetPixelMap(std::shared_ptr<PixelMap> & dataSource,const Size & targetSize,const AntiAliasingOption & option)220 bool ThumbnailUtils::ScaleTargetPixelMap(std::shared_ptr<PixelMap> &dataSource, const Size &targetSize,
221     const AntiAliasingOption &option)
222 {
223     MediaLibraryTracer tracer;
224     tracer.Start("ImageSource::ScaleTargetPixelMap");
225 
226     if (!PostProc::ScalePixelMapWithGPU(*(dataSource.get()), targetSize, option, true)) {
227         MEDIA_ERR_LOG("Fail to scale to target thumbnail, ScalePixelMapEx failed, targetSize: %{public}d * %{public}d",
228             targetSize.width, targetSize.height);
229         return false;
230     }
231     return true;
232 }
233 
CenterScaleEx(std::shared_ptr<PixelMap> & dataSource,const Size & desiredSize,const std::string path)234 bool ThumbnailUtils::CenterScaleEx(std::shared_ptr<PixelMap> &dataSource, const Size &desiredSize,
235     const std::string path)
236 {
237     if (dataSource->GetHeight() * dataSource->GetWidth() == 0) {
238         MEDIA_ERR_LOG("Invalid source size, ScalePixelMapEx failed, path: %{public}s",
239             DfxUtils::GetSafePath(path).c_str());
240         return false;
241     }
242     float sourceScale = static_cast<float>(dataSource->GetHeight()) / static_cast<float>(dataSource->GetWidth());
243     float scale = 1.0f;
244     if (sourceScale <= 1.0f) {
245         scale = static_cast<float>(desiredSize.height) / static_cast<float>(dataSource->GetHeight());
246     } else {
247         scale = static_cast<float>(desiredSize.width) / static_cast<float>(dataSource->GetWidth());
248     }
249 
250     MediaLibraryTracer tracer;
251     tracer.Start("CenterScaleEx");
252     if (std::abs(scale - 1.0f) > FLOAT_EPSILON) {
253         Size targetSize = {
254             static_cast<int32_t>(scale * dataSource->GetWidth()),
255             static_cast<int32_t>(scale * dataSource->GetHeight())
256         };
257         if (!ScaleTargetPixelMap(dataSource, targetSize, Media::AntiAliasingOption::GAUSS)) {
258             MEDIA_ERR_LOG("Fail in CenterScaleEx, ScalePixelMapEx failed, path: %{public}s",
259                 DfxUtils::GetSafePath(path).c_str());
260             return false;
261         }
262     }
263 
264     MediaLibraryTracer innerTracer;
265     innerTracer.Start("CenterScale");
266     PostProc postProc;
267     if (!postProc.CenterScale(desiredSize, *dataSource)) {
268         MEDIA_ERR_LOG("Fail in CenterScaleEx, CenterScale failed, path: %{public}s",
269             DfxUtils::GetSafePath(path).c_str());
270         return false;
271     }
272     return true;
273 }
274 
LoadImageFile(ThumbnailData & data,Size & desiredSize)275 bool ThumbnailUtils::LoadImageFile(ThumbnailData &data, Size &desiredSize)
276 {
277     mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
278     mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
279 
280     SourceLoader sourceLoader(desiredSize, data);
281     return sourceLoader.RunLoading();
282 }
283 
CompressImage(const shared_ptr<PixelMap> & pixelMap,vector<uint8_t> & data,bool isAstc,bool forceSdr,const ThumbnailQuality quality)284 bool ThumbnailUtils::CompressImage(const shared_ptr<PixelMap> &pixelMap, vector<uint8_t> &data, bool isAstc,
285     bool forceSdr, const ThumbnailQuality quality)
286 {
287     PackOption option = {
288         .format = isAstc ? THUMBASTC_FORMAT : THUMBNAIL_FORMAT,
289         .quality = static_cast<uint8_t>(isAstc ? ThumbnailQuality::ASTC_LOW_QUALITY : quality),
290         .numberHint = NUMBER_HINT_1,
291         .desiredDynamicRange = forceSdr ? EncodeDynamicRange::SDR :EncodeDynamicRange::AUTO
292     };
293     data.resize(max(pixelMap->GetByteCount(), MIN_COMPRESS_BUF_SIZE));
294 
295     MediaLibraryTracer tracer;
296     tracer.Start("imagePacker.StartPacking");
297     ImagePacker imagePacker;
298     uint32_t err = imagePacker.StartPacking(data.data(), data.size(), option);
299     tracer.Finish();
300     if (err != E_OK) {
301         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
302         return false;
303     }
304 
305     tracer.Start("imagePacker.AddImage");
306     err = imagePacker.AddImage(*pixelMap);
307     tracer.Finish();
308     if (err != E_OK) {
309         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
310         return false;
311     }
312 
313     tracer.Start("imagePacker.FinalizePacking");
314     int64_t packedSize = 0;
315     err = imagePacker.FinalizePacking(packedSize);
316     if (err != E_OK) {
317         MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
318         return false;
319     }
320 
321     data.resize(packedSize);
322     return true;
323 }
324 
CreateOutputPath(const ThumbnailData & data,const string & suffix)325 string ThumbnailUtils::CreateOutputPath(const ThumbnailData &data, const string &suffix)
326 {
327     string outputPath;
328     if (data.tracks.empty()) {
329         CHECK_AND_RETURN_RET_LOG(SaveFileCreateDir(data.path, suffix, outputPath) == E_OK,
330             "", "SaveFileCreateDir failed. path: %{public}s suffix: %{public}s",
331             DfxUtils::GetSafePath(data.path).c_str(), suffix.c_str());
332     } else {
333         CHECK_AND_RETURN_RET_LOG(SaveFileCreateDirHighlight(data.path, suffix, outputPath, data.timeStamp) == E_OK,
334             "", "SaveFileCreateDirHighlight failed. path: %{public}s suffix: %{public}s",
335             DfxUtils::GetSafePath(data.path).c_str(), suffix.c_str());
336     }
337     return outputPath;
338 }
339 
CompressPicture(ThumbnailData & data,const std::shared_ptr<Picture> & picture,const bool isSourceEx,string & tempOutputPath)340 bool ThumbnailUtils::CompressPicture(ThumbnailData &data, const std::shared_ptr<Picture>& picture,
341     const bool isSourceEx, string &tempOutputPath)
342 {
343     CHECK_AND_RETURN_RET_LOG(
344         THUMBNAIL_QUALITY_SET.count(data.thumbnailQuality),
345         false,
346         "compress thumbnail quality not in thumbnail quality set, quality: %{public}u",
347         static_cast<uint8_t>(data.thumbnailQuality));
348 
349     MEDIA_INFO_LOG("CompressPicture %{public}s", DfxUtils::GetSafePath(data.path).c_str());
350     auto outputPath = CreateOutputPath(data, isSourceEx ? THUMBNAIL_LCD_EX_SUFFIX : THUMBNAIL_LCD_SUFFIX);
351     CHECK_AND_RETURN_RET_LOG(!outputPath.empty(), false, "CreateOutputPath failed");
352     CHECK_AND_RETURN_RET_LOG(ThumbnailImageFrameWorkUtils::IsPictureValid(picture), false,
353         "Pictrue is invalid. path: %{public}s", DfxUtils::GetSafePath(data.path).c_str());
354     size_t lastSlash = outputPath.rfind('/');
355     if (lastSlash == string::npos || outputPath.size() <= lastSlash + 1) {
356         MEDIA_ERR_LOG("CompressPicture failed, failed to check outputPath: %{public}s, isSourceEx: %{public}d",
357             DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
358         return false;
359     }
360     tempOutputPath = outputPath.substr(0, lastSlash) + "/temp_" + data.dateModified + "_" +
361         outputPath.substr(lastSlash + 1);
362     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateAsset(tempOutputPath) == E_SUCCESS, false,
363         "CompressPicture failed, failed to create temp filter file: %{public}s, isSourceEx: %{public}d",
364         DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
365     Media::ImagePacker imagePacker;
366     PackOption option = {
367         .format = THUMBNAIL_FORMAT,
368         .quality = static_cast<uint8_t>(data.thumbnailQuality),
369         .numberHint = NUMBER_HINT_1,
370         .desiredDynamicRange = EncodeDynamicRange::AUTO,
371         .needsPackProperties = false
372     };
373     imagePacker.StartPacking(tempOutputPath, option);
374     imagePacker.AddPicture(*(picture));
375     imagePacker.FinalizePacking();
376     return true;
377 }
378 
SaveAfterPacking(ThumbnailData & data,const bool isSourceEx,const string & tempOutputPath)379 bool ThumbnailUtils::SaveAfterPacking(ThumbnailData &data, const bool isSourceEx, const string &tempOutputPath)
380 {
381     size_t size = -1;
382     MediaFileUtils::GetFileSize(tempOutputPath, size);
383     if (size == 0 && !MediaFileUtils::DeleteFile(tempOutputPath)) {
384         MEDIA_ERR_LOG("SaveAfterPacking failed, failed to delete temp filters file: %{public}s",
385             DfxUtils::GetSafePath(tempOutputPath).c_str());
386         return false;
387     }
388     auto outputPath = CreateOutputPath(data, isSourceEx ? THUMBNAIL_LCD_EX_SUFFIX : THUMBNAIL_LCD_SUFFIX);
389     CHECK_AND_RETURN_RET_LOG(!outputPath.empty(), false, "CreateOutputPath failed");
390     int ret = rename(tempOutputPath.c_str(), outputPath.c_str());
391     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, false,
392         "SaveAfterPacking failed, failed to rename temp filters file: %{public}s",
393         DfxUtils::GetSafePath(tempOutputPath).c_str());
394     if (MediaFileUtils::IsFileExists(tempOutputPath)) {
395         MEDIA_INFO_LOG("file: %{public}s exists, needs to be deleted", DfxUtils::GetSafePath(tempOutputPath).c_str());
396         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
397             "SaveAfterPacking delete failed: %{public}s", DfxUtils::GetSafePath(tempOutputPath).c_str());
398     }
399     return true;
400 }
401 
CancelAfterPacking(const string & tempOutputPath)402 void ThumbnailUtils::CancelAfterPacking(const string &tempOutputPath)
403 {
404     if (MediaFileUtils::IsFileExists(tempOutputPath)) {
405         MEDIA_INFO_LOG("CancelAfterPacking: %{public}s exists, needs deleted",
406             DfxUtils::GetSafePath(tempOutputPath).c_str());
407         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
408             "CancelAfterPacking delete failed: %{public}s", DfxUtils::GetSafePath(tempOutputPath).c_str());
409     }
410 }
411 
QueryThumbnailSet(ThumbRdbOpt & opts)412 shared_ptr<ResultSet> ThumbnailUtils::QueryThumbnailSet(ThumbRdbOpt &opts)
413 {
414     vector<string> column = {
415         MEDIA_DATA_DB_ID,
416         MEDIA_DATA_DB_FILE_PATH,
417         MEDIA_DATA_DB_MEDIA_TYPE,
418         MEDIA_DATA_DB_DATE_MODIFIED,
419     };
420 
421     vector<string> selectionArgs;
422     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + opts.row;
423 
424     RdbPredicates rdbPredicates(opts.table);
425     rdbPredicates.SetWhereClause(strQueryCondition);
426     rdbPredicates.SetWhereArgs(selectionArgs);
427     if (opts.store == nullptr) {
428         MEDIA_ERR_LOG("opts.store is nullptr");
429         return nullptr;
430     }
431     return opts.store->QueryByStep(rdbPredicates, column);
432 }
433 
QueryThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)434 shared_ptr<ResultSet> ThumbnailUtils::QueryThumbnailInfo(ThumbRdbOpt &opts,
435     ThumbnailData &data, int &err)
436 {
437     vector<string> column = {
438         MEDIA_DATA_DB_ID,
439         MEDIA_DATA_DB_FILE_PATH,
440         MEDIA_DATA_DB_MEDIA_TYPE,
441         MEDIA_DATA_DB_DATE_MODIFIED,
442     };
443     MediaLibraryTracer tracer;
444     tracer.Start("QueryThumbnailInfo");
445     auto resultSet = QueryThumbnailSet(opts);
446     CHECK_AND_RETURN_RET(ThumbnailRdbUtils::CheckResultSetCount(resultSet, err), nullptr);
447 
448     err = resultSet->GoToFirstRow();
449     if (err != E_OK) {
450         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
451             {KEY_OPT_TYPE, OptType::THUMB}};
452         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
453         return nullptr;
454     }
455 
456     ThumbnailRdbUtils::ParseQueryResult(resultSet, data, err, column);
457     return resultSet;
458 }
459 
QueryLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)460 bool ThumbnailUtils::QueryLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
461 {
462     vector<string> column = {
463         MEDIA_DATA_DB_ID,
464     };
465     RdbPredicates rdbPredicates(opts.table);
466     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
467         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
468     }
469     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
470     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
471     if (opts.store == nullptr) {
472         MEDIA_ERR_LOG("opts.store is nullptr");
473         return false;
474     }
475     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
476     if (resultSet == nullptr) {
477         MEDIA_ERR_LOG("ResultSet is nullptr");
478         return false;
479     }
480     int rowCount = 0;
481     err = resultSet->GetRowCount(rowCount);
482     resultSet.reset();
483     if (err != E_OK) {
484         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
485         return false;
486     }
487     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
488     if (rowCount <= 0) {
489         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
490         rowCount = 0;
491     }
492 
493     outLcdCount = rowCount;
494     return true;
495 }
496 
QueryLcdCountByTime(const int64_t & time,const bool & before,ThumbRdbOpt & opts,int & outLcdCount,int & err)497 bool ThumbnailUtils::QueryLcdCountByTime(const int64_t &time, const bool &before, ThumbRdbOpt &opts, int &outLcdCount,
498     int &err)
499 {
500     vector<string> column = {
501         MEDIA_DATA_DB_ID,
502     };
503     RdbPredicates rdbPredicates(opts.table);
504     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
505         if (before) {
506             rdbPredicates.LessThanOrEqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
507         } else {
508             rdbPredicates.GreaterThan(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
509         }
510     }
511     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
512     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
513     if (opts.store == nullptr) {
514         MEDIA_ERR_LOG("opts.store is nullptr");
515         return false;
516     }
517     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
518     if (resultSet == nullptr) {
519         MEDIA_ERR_LOG("ResultSet is nullptr");
520         return false;
521     }
522     int rowCount = 0;
523     err = resultSet->GetRowCount(rowCount);
524     resultSet.reset();
525     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "Failed to get row count %{public}d", err);
526     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
527     if (rowCount <= 0) {
528         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
529         rowCount = 0;
530     }
531 
532     outLcdCount = rowCount;
533     return true;
534 }
535 
QueryDistributeLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)536 bool ThumbnailUtils::QueryDistributeLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
537 {
538     vector<string> column = {
539         REMOTE_THUMBNAIL_DB_ID,
540     };
541     RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
542     rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
543     rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
544     if (opts.store == nullptr) {
545         MEDIA_ERR_LOG("opts.store is nullptr");
546         return false;
547     }
548     auto resultSet = opts.store->QueryByStep(rdbPredicates, column);
549     if (resultSet == nullptr) {
550         return false;
551     }
552     int rowCount = 0;
553     err = resultSet->GetRowCount(rowCount);
554     resultSet.reset();
555     if (err != E_OK) {
556         MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
557         return false;
558     }
559     MEDIA_INFO_LOG("rowCount is %{public}d", rowCount);
560     if (rowCount <= 0) {
561         MEDIA_INFO_LOG("No match! %{private}s", rdbPredicates.ToString().c_str());
562         rowCount = 0;
563     }
564     outLcdCount = rowCount;
565     return true;
566 }
567 
QueryAgingLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailData> & infos,int & err)568 bool ThumbnailUtils::QueryAgingLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
569     vector<ThumbnailData> &infos, int &err)
570 {
571     vector<string> column = {
572         MEDIA_DATA_DB_ID,
573         MEDIA_DATA_DB_FILE_PATH,
574         MEDIA_DATA_DB_MEDIA_TYPE,
575     };
576     RdbPredicates rdbPredicates(opts.table);
577     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
578     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
579 
580     rdbPredicates.Limit(LcdLimit);
581     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
582         rdbPredicates.OrderByAsc(PhotoColumn::PHOTO_LAST_VISIT_TIME);
583     }
584 
585     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
586         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
587     return true;
588 }
589 
QueryNoLcdInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)590 bool ThumbnailUtils::QueryNoLcdInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
591 {
592     vector<string> column = {
593         MEDIA_DATA_DB_ID,
594         MEDIA_DATA_DB_FILE_PATH,
595         MEDIA_DATA_DB_MEDIA_TYPE,
596         MEDIA_DATA_DB_POSITION,
597         MEDIA_DATA_DB_ORIENTATION,
598         PhotoColumn::PHOTO_EXIF_ROTATE,
599         MEDIA_DATA_DB_DATE_MODIFIED,
600     };
601     RdbPredicates rdbPredicates(opts.table);
602     rdbPredicates.EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, "0");
603     rdbPredicates.EqualTo(PhotoColumn::PHOTO_POSITION, "1");
604     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
605 
606     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
607         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
608     return true;
609 }
610 
QueryLocalNoLcdInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)611 bool ThumbnailUtils::QueryLocalNoLcdInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
612 {
613     if (opts.store == nullptr) {
614         MEDIA_ERR_LOG("opts.store is nullptr");
615         return false;
616     }
617     vector<string> column = {
618         MEDIA_DATA_DB_ID,
619         MEDIA_DATA_DB_FILE_PATH,
620         MEDIA_DATA_DB_MEDIA_TYPE,
621         MEDIA_DATA_DB_DATE_MODIFIED,
622     };
623     RdbPredicates rdbPredicates(opts.table);
624     rdbPredicates.EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, "0");
625     rdbPredicates.EqualTo(PhotoColumn::PHOTO_DIRTY, "1");
626     rdbPredicates.Limit(MAXIMUM_LCD_CHECK_NUM);
627     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
628 
629     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
630         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
631     return true;
632 }
633 
QueryNoHighlightPath(ThumbRdbOpt & opts,ThumbnailData & data,int & err)634 bool ThumbnailUtils::QueryNoHighlightPath(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
635 {
636     if (opts.store == nullptr) {
637         MEDIA_ERR_LOG("opts.store is nullptr");
638         return false;
639     }
640     vector<string> column = {
641         MEDIA_DATA_DB_FILE_PATH,
642     };
643     RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
644     rdbPredicates.EqualTo(PhotoColumn::MEDIA_ID, data.id);
645 
646     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfo(opts.store, rdbPredicates, column, data, err),
647         false, "QueryThumbnailDataInfo failed, err:%{public}d", err);
648     return true;
649 }
650 
QueryNoHighlightInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)651 bool ThumbnailUtils::QueryNoHighlightInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
652 {
653     if (opts.store == nullptr) {
654         MEDIA_ERR_LOG("opts.store is nullptr");
655         return false;
656     }
657     vector<string> column = {
658         MEDIA_DATA_DB_ID,
659         MEDIA_DATA_DB_VIDEO_TRACKS,
660         MEDIA_DATA_DB_HIGHLIGHT_TRIGGER,
661     };
662     RdbPredicates rdbPredicates(opts.table);
663     rdbPredicates.EqualTo(PhotoColumn::MEDIA_DATA_DB_HIGHLIGHT_TRIGGER, "0");
664     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
665     if (!ThumbnailRdbUtils::CheckResultSetCount(resultSet, err)) {
666         MEDIA_ERR_LOG("QueryNoHighlightInfos failed %{public}d", err);
667         return err == E_EMPTY_VALUES_BUCKET;
668     }
669 
670     err = resultSet->GoToFirstRow();
671     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "QueryNoHighlightInfos failed GoToFirstRow %{public}d", err);
672 
673     ThumbnailData data;
674     do {
675         ParseHighlightQueryResult(resultSet, data, err);
676         if (QueryNoHighlightPath(opts, data, err)) {
677             MEDIA_INFO_LOG("QueryNoHighlightPath data.path %{public}s",
678                 DfxUtils::GetSafePath(data.path).c_str());
679         }
680         data.frame = GetHighlightValue(data.tracks, "beginFrame");
681         data.timeStamp = GetHighlightValue(data.tracks, "beginTimeStamp");
682         if (!data.path.empty()) {
683             infos.push_back(data);
684         }
685     } while (resultSet->GoToNextRow() == E_OK);
686     return true;
687 }
688 
GetHighlightTracks(ThumbRdbOpt & opts,vector<int> & trackInfos,int32_t & err)689 bool ThumbnailUtils::GetHighlightTracks(ThumbRdbOpt &opts, vector<int> &trackInfos, int32_t &err)
690 {
691     if (opts.store == nullptr) {
692         MEDIA_ERR_LOG("opts.store is nullptr");
693         return false;
694     }
695     vector<string> column = {
696         MEDIA_DATA_DB_ID,
697         MEDIA_DATA_DB_VIDEO_TRACKS,
698     };
699     RdbPredicates rdbPredicates(opts.table);
700     rdbPredicates.EqualTo(PhotoColumn::MEDIA_ID, opts.row);
701     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
702     if (!ThumbnailRdbUtils::CheckResultSetCount(resultSet, err)) {
703         MEDIA_ERR_LOG("GetHighlightTracks failed %{public}d", err);
704         if (err == E_EMPTY_VALUES_BUCKET) {
705             return true;
706         }
707         return false;
708     }
709 
710     err = resultSet->GoToFirstRow();
711     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "GetHighlightTracks failed GoToFirstRow %{public}d", err);
712 
713     ThumbnailData data;
714     std::string timeStamp;
715     do {
716         ParseHighlightQueryResult(resultSet, data, err);
717         timeStamp = GetHighlightValue(data.tracks, "beginTimeStamp");
718         trackInfos.push_back(std::atoi(timeStamp.c_str()));
719     } while (resultSet->GoToNextRow() == E_OK);
720     return true;
721 }
722 
QueryHighlightTriggerPath(ThumbRdbOpt & opts,ThumbnailData & data,int & err)723 bool ThumbnailUtils::QueryHighlightTriggerPath(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
724 {
725     if (QueryNoHighlightPath(opts, data, err)) {
726         MEDIA_INFO_LOG("QueryHighlightTriggerPath path: %{public}s",
727             DfxUtils::GetSafePath(data.path).c_str());
728     }
729     data.frame = GetHighlightValue(data.tracks, "beginFrame");
730     data.timeStamp = GetHighlightValue(data.tracks, "beginTimeStamp");
731     return true;
732 }
733 
GetHighlightValue(const std::string & str,const std::string & key)734 std::string ThumbnailUtils::GetHighlightValue(const std::string &str, const std::string &key)
735 {
736     std::size_t keyPos = str.find(key);
737     if (keyPos == std::string::npos) {
738         return "";
739     }
740     std::size_t colonPos = str.find(":", keyPos);
741     if (colonPos == std::string::npos) {
742         return "";
743     }
744     std::size_t commaPos = str.find(",", colonPos);
745     if (commaPos == std::string::npos) {
746         commaPos = str.find("}", colonPos);
747         if (commaPos == std::string::npos) {
748             return "";
749         }
750     }
751     std::string valueStr = str.substr(colonPos + 1, commaPos - colonPos - 1);
752     return valueStr;
753 }
754 
QueryLocalNoThumbnailInfos(ThumbRdbOpt & opt,vector<ThumbnailData> & infos,int & err)755 bool ThumbnailUtils::QueryLocalNoThumbnailInfos(ThumbRdbOpt &opt, vector<ThumbnailData> &infos, int &err)
756 {
757     vector<string> column = {
758         MEDIA_DATA_DB_ID,
759         MEDIA_DATA_DB_FILE_PATH,
760         MEDIA_DATA_DB_MEDIA_TYPE,
761         MEDIA_DATA_DB_THUMBNAIL_READY,
762         MEDIA_DATA_DB_DATE_MODIFIED,
763         PhotoColumn::PHOTO_LCD_VISIT_TIME,
764     };
765     RdbPredicates rdbPredicates(opt.table);
766     rdbPredicates.EqualTo(PhotoColumn::PHOTO_POSITION, "1");
767     rdbPredicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, "0")->Or()->
768         EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY,
769         std::to_string(static_cast<int32_t>(ThumbnailReady::GENERATE_THUMB_LATER)))
770         ->EndWrap();
771     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
772     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
773     rdbPredicates.Limit(THUMBNAIL_QUERY_MIN);
774     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
775 
776     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opt.store, rdbPredicates, column, infos, err),
777         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
778     return true;
779 }
780 
QueryNoThumbnailInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)781 bool ThumbnailUtils::QueryNoThumbnailInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
782 {
783     vector<string> column = {
784         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH,
785         MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_DATE_MODIFIED,
786     };
787     RdbPredicates rdbPredicates(opts.table);
788     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
789         rdbPredicates.EqualTo(PhotoColumn::PHOTO_LAST_VISIT_TIME, "0");
790     }
791     if ((opts.table == PhotoColumn::PHOTOS_TABLE) || (opts.table == AudioColumn::AUDIOS_TABLE)) {
792         rdbPredicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, "0");
793     } else {
794         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
795     }
796     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
797     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
798     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
799     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
800         // Filter data that Only exists in Cloud to avoid cosuming data of downloading the original image
801         // meaning of Position: 1--only in local, 2--only in cloud, 3--both in local and cloud
802         rdbPredicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->
803             EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
804     }
805 
806     rdbPredicates.Limit(THUMBNAIL_QUERY_MAX);
807     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
808     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
809         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
810     return true;
811 }
812 
QueryUpgradeThumbnailInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,bool isWifiConnected,int & err)813 bool ThumbnailUtils::QueryUpgradeThumbnailInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos,
814     bool isWifiConnected, int &err)
815 {
816     vector<string> column = {
817         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_DATE_ADDED,
818         MEDIA_DATA_DB_NAME, MEDIA_DATA_DB_POSITION, MEDIA_DATA_DB_DATE_TAKEN, MEDIA_DATA_DB_DATE_MODIFIED,
819         MEDIA_DATA_DB_ORIENTATION, PhotoColumn::PHOTO_EXIF_ROTATE,
820     };
821 
822     RdbPredicates rdbPredicates(opts.table);
823     rdbPredicates.EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, std::to_string(
824         static_cast<int32_t>(ThumbnailReady::THUMB_UPGRADE)));
825     if (!isWifiConnected) {
826         rdbPredicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, "2");
827     }
828     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
829 
830     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
831         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
832     return true;
833 }
834 
QueryNoAstcInfosRestored(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err,const int32_t & restoreAstcCount)835 bool ThumbnailUtils::QueryNoAstcInfosRestored(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err,
836     const int32_t &restoreAstcCount)
837 {
838     vector<string> column = {
839         MEDIA_DATA_DB_ID,
840         MEDIA_DATA_DB_FILE_PATH,
841         MEDIA_DATA_DB_MEDIA_TYPE,
842         MEDIA_DATA_DB_DATE_ADDED,
843         MEDIA_DATA_DB_NAME,
844         MEDIA_DATA_DB_POSITION,
845         MEDIA_DATA_DB_DATE_TAKEN,
846         MEDIA_DATA_DB_DATE_MODIFIED,
847     };
848     RdbPredicates rdbPredicates(opts.table);
849     rdbPredicates.OrderByDesc(MediaColumn::MEDIA_DATE_TAKEN);
850     rdbPredicates.Limit(restoreAstcCount);
851     rdbPredicates.EqualTo(PhotoColumn::PHOTO_POSITION, "1");
852     rdbPredicates.EqualTo(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, "0");
853     rdbPredicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, "0");
854     rdbPredicates.EqualTo(MediaColumn::MEDIA_TIME_PENDING, "0");
855     rdbPredicates.EqualTo(MediaColumn::MEDIA_HIDDEN, "0");
856     rdbPredicates.EqualTo(PhotoColumn::PHOTO_IS_TEMP, "0");
857     rdbPredicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL, "1");
858     rdbPredicates.EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, "0");
859     rdbPredicates.EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, "0");
860 
861     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
862         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
863     return true;
864 }
865 
QueryNoAstcInfos(ThumbRdbOpt & opts,vector<ThumbnailData> & infos,int & err)866 bool ThumbnailUtils::QueryNoAstcInfos(ThumbRdbOpt &opts, vector<ThumbnailData> &infos, int &err)
867 {
868     vector<string> column = {
869         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_NAME,
870         MEDIA_DATA_DB_POSITION, MEDIA_DATA_DB_ORIENTATION, PhotoColumn::PHOTO_EXIF_ROTATE,
871         MEDIA_DATA_DB_DATE_TAKEN, MEDIA_DATA_DB_DATE_MODIFIED,
872     };
873     RdbPredicates rdbPredicates(opts.table);
874     rdbPredicates.BeginWrap()
875         ->EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "0")
876         ->Or()->EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "2")
877         ->Or()->EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "7")
878         ->EndWrap();
879     rdbPredicates.BeginWrap()
880         ->BeginWrap()
881         ->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()->EqualTo(PhotoColumn::PHOTO_POSITION, "3")
882         ->EndWrap()->Or()->BeginWrap()
883         ->EqualTo(PhotoColumn::PHOTO_POSITION, "2")->And()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, "0")
884         ->EndWrap()->EndWrap();
885     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
886 
887     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicates, column, infos, err),
888         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
889     return true;
890 }
891 
QueryNewThumbnailCount(ThumbRdbOpt & opts,const int64_t & time,int & count,int & err)892 bool ThumbnailUtils::QueryNewThumbnailCount(ThumbRdbOpt &opts, const int64_t &time, int &count,
893     int &err)
894 {
895     vector<string> column = {
896         MEDIA_DATA_DB_ID,
897     };
898     RdbPredicates rdbPredicates(opts.table);
899     if (opts.table == PhotoColumn::PHOTOS_TABLE) {
900         rdbPredicates.GreaterThan(PhotoColumn::PHOTO_LAST_VISIT_TIME, to_string(time));
901     }
902     if (opts.table == MEDIALIBRARY_TABLE) {
903         rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
904     } else {
905         rdbPredicates.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
906     }
907     rdbPredicates.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
908     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
909     rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
910 
911     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
912     if (opts.store == nullptr) {
913         MEDIA_ERR_LOG("opts.store is nullptr");
914         return false;
915     }
916     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
917     if (resultSet == nullptr) {
918         MEDIA_ERR_LOG("ResultSet is nullptr");
919         return false;
920     }
921     int rowCount = 0;
922     err = resultSet->GetRowCount(rowCount);
923     resultSet.reset();
924     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "Failed GoToFirstRow %{public}d", err);
925     MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
926     if (rowCount <= 0) {
927         MEDIA_INFO_LOG("No match! %{public}s", rdbPredicates.ToString().c_str());
928         rowCount = 0;
929     }
930 
931     count = rowCount;
932     return true;
933 }
934 
CacheLcdInfo(ThumbRdbOpt & opts,ThumbnailData & data)935 bool ThumbnailUtils::CacheLcdInfo(ThumbRdbOpt &opts, ThumbnailData &data)
936 {
937     CHECK_AND_RETURN_RET_LOG(opts.table == PhotoColumn::PHOTOS_TABLE, false,
938         "Not %{public}s table, table: %{public}s", PhotoColumn::PHOTOS_TABLE.c_str(), opts.table.c_str());
939 
940     ValuesBucket& values = data.rdbUpdateCache;
941 
942     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, MediaFileUtils::UTCTimeMilliSeconds());
943     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(LcdReady::GENERATE_LCD_COMPLETED));
944 
945     Size lcdSize;
946     if (GetLocalThumbSize(data, ThumbnailType::LCD, lcdSize)) {
947         SetThumbnailSizeValue(values, lcdSize, PhotoColumn::PHOTO_LCD_SIZE);
948     }
949 
950     return true;
951 }
952 
CacheInvalidLcdInfo(ThumbnailData & data)953 void ThumbnailUtils::CacheInvalidLcdInfo(ThumbnailData &data)
954 {
955     ValuesBucket &values = data.rdbUpdateCache;
956     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(LcdReady::GENERATE_LCD_LATER));
957 }
958 
UpdateHighlightInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)959 bool ThumbnailUtils::UpdateHighlightInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
960 {
961     if (opts.store == nullptr) {
962         MEDIA_ERR_LOG("opts.store is nullptr");
963         return false;
964     }
965     ValuesBucket values;
966     int changedRows;
967 
968     MediaLibraryTracer tracer;
969     tracer.Start("UpdateHighlightInfo opts.store->Update");
970     values.PutLong(PhotoColumn::MEDIA_DATA_DB_HIGHLIGHT_TRIGGER, 1);
971 
972     RdbPredicates rdbPredicates(opts.table);
973     rdbPredicates.EqualTo(MEDIA_DATA_DB_ID, data.id);
974     rdbPredicates.EqualTo(MEDIA_DATA_DB_VIDEO_TRACKS, data.tracks);
975     err = opts.store->Update(changedRows, values, rdbPredicates);
976     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, false, "UpdateHighlightInfo failed! %{public}d", err);
977     return true;
978 }
979 
UpdateLcdReadyStatus(ThumbRdbOpt & opts,ThumbnailData & data,int & err,LcdReady status)980 bool ThumbnailUtils::UpdateLcdReadyStatus(ThumbRdbOpt &opts, ThumbnailData &data, int &err, LcdReady status)
981 {
982     ValuesBucket values;
983     int changedRows;
984     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, static_cast<int64_t>(status));
985     if (opts.store == nullptr) {
986         MEDIA_ERR_LOG("opts.store is nullptr");
987         return false;
988     }
989     err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
990         vector<string> { opts.row });
991     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, false,
992         "UpdateLcdReadyStatus rdbStore Update failed! %{public}d", err);
993     return true;
994 }
995 
CleanThumbnailInfo(ThumbRdbOpt & opts,bool withThumb,bool withLcd)996 bool ThumbnailUtils::CleanThumbnailInfo(ThumbRdbOpt &opts, bool withThumb, bool withLcd)
997 {
998     ValuesBucket values;
999     if (withThumb) {
1000         values.PutNull(MEDIA_DATA_DB_THUMBNAIL);
1001     }
1002     if (withLcd) {
1003         values.PutInt(MEDIA_DATA_DB_DIRTY, static_cast<int32_t>(DirtyType::TYPE_SYNCED));
1004         if (opts.table == MEDIALIBRARY_TABLE) {
1005             values.PutNull(MEDIA_DATA_DB_LCD);
1006         }
1007         if (opts.table == PhotoColumn::PHOTOS_TABLE) {
1008             values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, 0);
1009         }
1010     }
1011     int changedRows;
1012     if (opts.store == nullptr) {
1013         MEDIA_ERR_LOG("opts.store is nullptr");
1014         return false;
1015     }
1016     auto err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1017         vector<string> { opts.row });
1018     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, false, "RdbStore Update failed! %{public}d", err);
1019     return true;
1020 }
1021 
PostProcPixelMapSource(ThumbnailData & data)1022 void ThumbnailUtils::PostProcPixelMapSource(ThumbnailData &data)
1023 {
1024     auto pixelMap = data.source.GetPixelMap();
1025     if (pixelMap == nullptr) {
1026         return;
1027     }
1028     pixelMap->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
1029     if (ThumbnailUtils::NeedRotateThumbnail(data)) {
1030         if (data.needGenerateExThumbnail) {
1031             std::shared_ptr<PixelMap> copySource = ThumbnailImageFrameWorkUtils::CopyPixelMapSource(pixelMap);
1032             data.source.SetPixelMapEx(copySource);
1033         }
1034         ThumbnailImageFrameWorkUtils::FlipAndRotatePixelMap(pixelMap, data.exifRotate);
1035     }
1036 
1037     // PixelMap has been rotated, fix the exif orientation to zero degree.
1038     pixelMap->ModifyImageProperty(PHOTO_DATA_IMAGE_ORIENTATION, DEFAULT_EXIF_ORIENTATION);
1039 }
1040 
PostProcPictureSource(ThumbnailData & data)1041 void ThumbnailUtils::PostProcPictureSource(ThumbnailData &data)
1042 {
1043     auto picture = data.source.GetPicture();
1044     if (picture == nullptr) {
1045         return;
1046     }
1047     auto pixelMap = picture->GetMainPixel();
1048     auto gainMap = picture->GetGainmapPixelMap();
1049     if (pixelMap == nullptr || gainMap == nullptr) {
1050         return;
1051     }
1052     if (ThumbnailUtils::NeedRotateThumbnail(data)) {
1053         if (data.needGenerateExThumbnail) {
1054             std::shared_ptr<Picture> copySource = ThumbnailImageFrameWorkUtils::CopyPictureSource(picture);
1055             data.source.SetPictureEx(copySource);
1056         }
1057         ThumbnailImageFrameWorkUtils::FlipAndRotatePicture(picture, data.exifRotate);
1058     }
1059 }
1060 
LoadSourceImage(ThumbnailData & data)1061 bool ThumbnailUtils::LoadSourceImage(ThumbnailData &data)
1062 {
1063     if (!data.source.IsEmptySource()) {
1064         return true;
1065     }
1066     MediaLibraryTracer tracer;
1067     tracer.Start("LoadSourceImage");
1068     if (data.mediaType == -1) {
1069         auto extension = MediaFileUtils::GetExtensionFromPath(data.path);
1070         auto mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension);
1071         data.mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1072     }
1073 
1074     bool ret = false;
1075     Size desiredSize;
1076     if (data.mediaType == MEDIA_TYPE_AUDIO) {
1077         ret = LoadAudioFile(data, desiredSize);
1078     } else {
1079         ret = LoadImageFile(data, desiredSize);
1080     }
1081     if (!ret || (data.source.IsEmptySource())) {
1082         return false;
1083     }
1084     tracer.Finish();
1085 
1086     auto pixelMap = data.source.GetPixelMap();
1087     if (data.loaderOpts.decodeInThumbSize && !CenterScaleEx(pixelMap, desiredSize, data.path)) {
1088         MEDIA_ERR_LOG("thumbnail center crop failed [%{private}s]", data.id.c_str());
1089         return false;
1090     }
1091 
1092     if (data.source.HasPictureSource()) {
1093         PostProcPictureSource(data);
1094     } else {
1095         PostProcPixelMapSource(data);
1096     }
1097     return true;
1098 }
1099 
ScaleFastThumb(ThumbnailData & data,const Size & size)1100 bool ThumbnailUtils::ScaleFastThumb(ThumbnailData &data, const Size &size)
1101 {
1102     MediaLibraryTracer tracer;
1103     tracer.Start("ScaleFastThumb");
1104 
1105     auto pixelMap = data.source.GetPixelMap();
1106     if (!CenterScaleEx(pixelMap, size, data.path)) {
1107         MEDIA_ERR_LOG("Fast thumb center crop failed [%{private}s]", data.id.c_str());
1108         return false;
1109     }
1110     return true;
1111 }
1112 
SaveFile(const string & fileName,uint8_t * output,int writeSize)1113 static int SaveFile(const string &fileName, uint8_t *output, int writeSize)
1114 {
1115     string tempFileName = fileName + ".tmp";
1116     const mode_t fileMode = 0644;
1117     mode_t mask = umask(0);
1118     UniqueFd fd(open(tempFileName.c_str(), O_WRONLY | O_CREAT | O_TRUNC, fileMode));
1119     umask(mask);
1120     if (fd.Get() < 0) {
1121         if (errno == EEXIST) {
1122             UniqueFd fd(open(tempFileName.c_str(), O_WRONLY | O_TRUNC, fileMode));
1123         }
1124         if (fd.Get() < 0) {
1125             int err = errno;
1126             std::string fileParentPath = MediaFileUtils::GetParentPath(tempFileName);
1127             MEDIA_ERR_LOG("save failed! status %{public}d, filePath: %{public}s exists: %{public}d, parent path "
1128                 "exists: %{public}d", err, DfxUtils::GetSafePath(tempFileName).c_str(), MediaFileUtils::IsFileExists(
1129                     tempFileName), MediaFileUtils::IsFileExists(fileParentPath));
1130             if (err == EACCES) {
1131                 MediaFileUtils::PrintStatInformation(fileParentPath);
1132             }
1133             return -err;
1134         }
1135     }
1136     int ret = write(fd.Get(), output, writeSize);
1137     CHECK_AND_RETURN_RET_LOG(ret >= 0, -errno, "write failed errno %{public}d", errno);
1138     int32_t errCode = fsync(fd.Get());
1139     CHECK_AND_RETURN_RET_LOG(errCode >= 0, -errno, "fsync failed errno %{public}d", errno);
1140     close(fd.Release());
1141 
1142     if (MediaFileUtils::IsFileExists(fileName)) {
1143         MEDIA_INFO_LOG("file: %{public}s exists and needs to be deleted", DfxUtils::GetSafePath(fileName).c_str());
1144         if (!MediaFileUtils::DeleteFile(fileName)) {
1145             MEDIA_ERR_LOG("delete file: %{public}s failed", DfxUtils::GetSafePath(fileName).c_str());
1146             return -errno;
1147         }
1148     }
1149     errCode = MediaFileUtils::ModifyAsset(tempFileName, fileName);
1150     if (errCode != E_OK) {
1151         int32_t lastErrno = errno;
1152         if (!MediaFileUtils::DeleteFile(tempFileName)) {
1153             MEDIA_WARN_LOG("Delete tmp thumb error: %{public}d, name: %{public}s",
1154                 errno, DfxUtils::GetSafePath(tempFileName).c_str());
1155         }
1156         if (errCode == E_FILE_EXIST || (errCode == E_FILE_OPER_FAIL && lastErrno == EEXIST)) {
1157             return E_OK;
1158         }
1159         return errCode;
1160     }
1161     return ret;
1162 }
1163 
SaveFileCreateDir(const string & path,const string & suffix,string & fileName)1164 int ThumbnailUtils::SaveFileCreateDir(const string &path, const string &suffix, string &fileName)
1165 {
1166     fileName = GetThumbnailPath(path, suffix);
1167     string dir = MediaFileUtils::GetParentPath(fileName);
1168     if (!MediaFileUtils::CreateDirectory(dir)) {
1169         MEDIA_ERR_LOG("Fail to create directory, fileName: %{public}s", DfxUtils::GetSafePath(fileName).c_str());
1170         return -errno;
1171     }
1172     return E_OK;
1173 }
1174 
SaveFileCreateDirHighlight(const string & path,const string & suffix,string & fileName,const string & timeStamp)1175 int ThumbnailUtils::SaveFileCreateDirHighlight(const string &path, const string &suffix,
1176     string &fileName, const string &timeStamp)
1177 {
1178     fileName = GetThumbnailPathHighlight(path, suffix, timeStamp);
1179     string dir = MediaFileUtils::GetParentPath(fileName);
1180     if (!MediaFileUtils::CreateDirectory(dir)) {
1181         MEDIA_ERR_LOG("Fail to create highlight directory, fileName: %{public}s",
1182             DfxUtils::GetSafePath(fileName).c_str());
1183         return -errno;
1184     }
1185     return E_OK;
1186 }
1187 
ToSaveFile(ThumbnailData & data,const string & fileName,uint8_t * output,const int & writeSize)1188 int ThumbnailUtils::ToSaveFile(ThumbnailData &data, const string &fileName, uint8_t *output, const int &writeSize)
1189 {
1190     int ret = SaveFile(fileName, output, writeSize);
1191     if (ret < 0) {
1192         MEDIA_ERR_LOG("Fail to save File, err: %{public}d", ret);
1193         return ret;
1194     } else if (ret != writeSize) {
1195         MEDIA_ERR_LOG("Fail to save File, insufficient space left.");
1196         return E_NO_SPACE;
1197     }
1198     return E_OK;
1199 }
1200 
TrySaveFile(ThumbnailData & data,ThumbnailType type)1201 int ThumbnailUtils::TrySaveFile(ThumbnailData &data, ThumbnailType type)
1202 {
1203     string suffix;
1204     uint8_t *output;
1205     uint32_t writeSize;
1206     switch (type) {
1207         case ThumbnailType::THUMB:
1208             suffix = THUMBNAIL_THUMB_SUFFIX;
1209             output = data.thumbnail.data();
1210             writeSize = data.thumbnail.size();
1211             break;
1212         case ThumbnailType::THUMB_ASTC:
1213             suffix = THUMBNAIL_THUMB_ASTC_SUFFIX;
1214             output = data.thumbAstc.data();
1215             writeSize = data.thumbAstc.size();
1216             break;
1217         case ThumbnailType::LCD:
1218             suffix = THUMBNAIL_LCD_SUFFIX;
1219             output = data.lcd.data();
1220             writeSize = data.lcd.size();
1221             break;
1222         case ThumbnailType::MTH_ASTC:
1223             output = data.monthAstc.data();
1224             writeSize = data.monthAstc.size();
1225             break;
1226         case ThumbnailType::YEAR_ASTC:
1227             output = data.yearAstc.data();
1228             writeSize = data.yearAstc.size();
1229             break;
1230         case ThumbnailType::LCD_EX:
1231             suffix = THUMBNAIL_LCD_EX_SUFFIX;
1232             output = data.lcd.data();
1233             writeSize = data.lcd.size();
1234             break;
1235         case ThumbnailType::THUMB_EX:
1236             suffix = THUMBNAIL_THUMB_EX_SUFFIX;
1237             output = data.thumbnail.data();
1238             writeSize = data.thumbnail.size();
1239             break;
1240         default:
1241             return E_INVALID_ARGUMENTS;
1242     }
1243     if (writeSize <= 0) {
1244         return E_THUMBNAIL_LOCAL_CREATE_FAIL;
1245     }
1246     if (type == ThumbnailType::MTH_ASTC || type == ThumbnailType::YEAR_ASTC) {
1247         return SaveAstcDataToKvStore(data, type);
1248     }
1249     return SaveThumbDataToLocalDir(data, suffix, output, writeSize);
1250 }
1251 
SaveThumbDataToLocalDir(ThumbnailData & data,const std::string & suffix,uint8_t * output,const int writeSize)1252 int ThumbnailUtils::SaveThumbDataToLocalDir(ThumbnailData &data, const std::string &suffix,
1253     uint8_t *output, const int writeSize)
1254 {
1255     string fileName;
1256     int ret;
1257     if (!data.tracks.empty()) {
1258         ret = SaveFileCreateDirHighlight(data.path, suffix, fileName, data.timeStamp);
1259     } else {
1260         ret = SaveFileCreateDir(data.path, suffix, fileName);
1261     }
1262 
1263     if (ret != E_OK) {
1264         MEDIA_ERR_LOG("SaveThumbDataToLocalDir create dir path %{public}s err %{public}d",
1265             DfxUtils::GetSafePath(data.path).c_str(), ret);
1266         return ret;
1267     }
1268     ret = ToSaveFile(data, fileName, output, writeSize);
1269     if (ret < 0) {
1270         MEDIA_ERR_LOG("SaveThumbDataToLocalDir ToSaveFile path %{public}s err %{public}d",
1271             DfxUtils::GetSafePath(data.path).c_str(), ret);
1272         return ret;
1273     }
1274     return E_OK;
1275 }
1276 
SetSource(shared_ptr<AVMetadataHelper> avMetadataHelper,const string & path)1277 int32_t ThumbnailUtils::SetSource(shared_ptr<AVMetadataHelper> avMetadataHelper, const string &path)
1278 {
1279     if (avMetadataHelper == nullptr) {
1280         MEDIA_ERR_LOG("avMetadataHelper == nullptr");
1281         return E_ERR;
1282     }
1283     MEDIA_DEBUG_LOG("path = %{public}s", DfxUtils::GetSafePath(path).c_str());
1284 
1285     string absFilePath;
1286     if (!PathToRealPath(path, absFilePath)) {
1287         MEDIA_ERR_LOG("Failed to open a nullptr path, errno=%{public}d, path:%{public}s",
1288             errno, DfxUtils::GetSafePath(path).c_str());
1289         return E_ERR;
1290     }
1291 
1292     int32_t fd = open(absFilePath.c_str(), O_RDONLY);
1293     if (fd < 0) {
1294         MEDIA_ERR_LOG("Open file failed, err %{public}d, file: %{public}s exists: %{public}d",
1295             errno, DfxUtils::GetSafePath(absFilePath).c_str(), MediaFileUtils::IsFileExists(absFilePath));
1296         return E_ERR;
1297     }
1298     struct stat64 st;
1299     if (fstat64(fd, &st) != 0) {
1300         MEDIA_ERR_LOG("Get file state failed, err %{public}d", errno);
1301         (void)close(fd);
1302         return E_ERR;
1303     }
1304     int64_t length = static_cast<int64_t>(st.st_size);
1305     int32_t ret = avMetadataHelper->SetSource(fd, 0, length, AV_META_USAGE_PIXEL_MAP);
1306     if (ret != 0) {
1307         DfxManager::GetInstance()->HandleThumbnailError(absFilePath, DfxType::AV_SET_SOURCE, ret);
1308         (void)close(fd);
1309         return E_ERR;
1310     }
1311     (void)close(fd);
1312     return E_SUCCESS;
1313 }
1314 
ResizeImage(const vector<uint8_t> & data,const Size & size,unique_ptr<PixelMap> & pixelMap)1315 bool ThumbnailUtils::ResizeImage(const vector<uint8_t> &data, const Size &size, unique_ptr<PixelMap> &pixelMap)
1316 {
1317     MediaLibraryTracer tracer;
1318     tracer.Start("ResizeImage");
1319     CHECK_AND_RETURN_RET_LOG(data.size() != 0, false, "Data is empty");
1320 
1321     tracer.Start("ImageSource::CreateImageSource");
1322     uint32_t err = E_OK;
1323     SourceOptions opts;
1324     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(data.data(),
1325         data.size(), opts, err);
1326     CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, false, "imageSource is nullptr");
1327     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "Failed to create image source %{public}d", err);
1328     tracer.Finish();
1329 
1330     tracer.Start("imageSource->CreatePixelMap");
1331     DecodeOptions decodeOpts;
1332     decodeOpts.desiredSize.width = size.width;
1333     decodeOpts.desiredSize.height = size.height;
1334     pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
1335     CHECK_AND_RETURN_RET_LOG(err == E_SUCCESS, false, "Failed to create pixelmap %{public}d", err);
1336 
1337     return true;
1338 }
1339 
DeleteAllThumbFilesAndAstc(ThumbRdbOpt & opts,ThumbnailData & data)1340 bool ThumbnailUtils::DeleteAllThumbFilesAndAstc(ThumbRdbOpt &opts, ThumbnailData &data)
1341 {
1342     CHECK_AND_RETURN_RET_LOG(opts.store != nullptr, false, "RdbStore is nullptr");
1343     if (data.path.empty()) {
1344         int err = 0;
1345         auto rdbSet = QueryThumbnailInfo(opts, data, err);
1346         CHECK_AND_RETURN_RET_LOG(rdbSet != nullptr, false, "QueryThumbnailInfo Faild [ %{public}d ]", err);
1347     }
1348     ValuesBucket values;
1349     int changedRows;
1350     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, 0);
1351     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, 0);
1352     int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
1353         vector<string> { data.id });
1354     CHECK_AND_WARN_LOG(err == NativeRdb::E_OK, "RdbStore Update Failed Before Delete Thumbnail! %{public}d", err);
1355     MEDIA_INFO_LOG("Start DeleteAllThumbFilesAndAstc, table:%{public}s, id: %{public}s, dateKey:%{public}s, "
1356         "path:%{public}s", opts.table.c_str(), data.id.c_str(), data.dateTaken.c_str(),
1357         DfxUtils::GetSafePath(data.path).c_str());
1358 
1359     bool isDeleteAllThumbFiles = ThumbnailFileUtils::DeleteAllThumbFiles(data);
1360     if (opts.table == AudioColumn::AUDIOS_TABLE) {
1361         return isDeleteAllThumbFiles;
1362     }
1363 
1364     DropThumbnailSize(opts, data);
1365     if (data.dateTaken.empty()) {
1366         return isDeleteAllThumbFiles;
1367     }
1368     bool isDeleteAstc = ThumbnailFileUtils::DeleteMonthAndYearAstc(data);
1369     return isDeleteAllThumbFiles && isDeleteAstc;
1370 }
1371 
DeleteThumbnailDirAndAstc(const ThumbRdbOpt & opts,const ThumbnailData & data)1372 bool ThumbnailUtils::DeleteThumbnailDirAndAstc(const ThumbRdbOpt &opts, const ThumbnailData &data)
1373 {
1374     MEDIA_INFO_LOG("Start DeleteThumbnailDirAndAstc, table:%{public}s, id: %{public}s, dateKey:%{public}s, "
1375         "path:%{public}s", opts.table.c_str(), data.id.c_str(), data.dateTaken.c_str(),
1376         DfxUtils::GetSafePath(data.path).c_str());
1377     bool isDeleteThumbnailDir = ThumbnailFileUtils::DeleteThumbnailDir(data);
1378     if (opts.table == AudioColumn::AUDIOS_TABLE) {
1379         return isDeleteThumbnailDir;
1380     }
1381 
1382     DropThumbnailSize(opts, data);
1383     bool isDeleteAstc = ThumbnailFileUtils::DeleteMonthAndYearAstc(data);
1384     return isDeleteThumbnailDir && isDeleteAstc;
1385 }
1386 
BatchDeleteThumbnailDirAndAstc(const ThumbRdbOpt & opts,const ThumbnailDataBatch & dataBatch)1387 bool ThumbnailUtils::BatchDeleteThumbnailDirAndAstc(const ThumbRdbOpt &opts, const ThumbnailDataBatch &dataBatch)
1388 {
1389     size_t dataBatchSize = dataBatch.ids.size();
1390     CHECK_AND_RETURN_RET_LOG(dataBatchSize == dataBatch.paths.size() && dataBatchSize == dataBatch.dateTakens.size(),
1391         false, "Failed to check dataBatch");
1392     MEDIA_INFO_LOG("Start BatchDeleteThumbnailDirAndAstc, table:%{public}s, size:%{public}d",
1393         opts.table.c_str(), static_cast<int32_t>(dataBatchSize));
1394 
1395     bool isDeleteThumbnailDir = true;
1396     for (const string &path : dataBatch.paths) {
1397         ThumbnailData data;
1398         data.path = path;
1399         isDeleteThumbnailDir = ThumbnailFileUtils::DeleteThumbnailDir(data) && isDeleteThumbnailDir;
1400     }
1401 
1402     if (opts.table == AudioColumn::AUDIOS_TABLE) {
1403         return isDeleteThumbnailDir;
1404     }
1405 
1406     BatchDropThumbnailSize(dataBatch);
1407     bool isDeleteAstc = ThumbnailFileUtils::BatchDeleteMonthAndYearAstc(dataBatch);
1408     return isDeleteThumbnailDir && isDeleteAstc;
1409 }
1410 
DoUpdateAstcDateTaken(ThumbRdbOpt & opts,ThumbnailData & data)1411 bool ThumbnailUtils::DoUpdateAstcDateTaken(ThumbRdbOpt &opts, ThumbnailData &data)
1412 {
1413     MEDIA_INFO_LOG("Start DoUpdateAstcDateTaken, id: %{public}s", opts.row.c_str());
1414     return UpdateAstcDateTakenFromKvStore(opts, data);
1415 }
1416 
UTCTimeMilliSeconds()1417 int64_t ThumbnailUtils::UTCTimeMilliSeconds()
1418 {
1419     struct timespec t;
1420     constexpr int64_t SEC_TO_MSEC = 1e3;
1421     constexpr int64_t MSEC_TO_NSEC = 1e6;
1422     clock_gettime(CLOCK_REALTIME, &t);
1423     return t.tv_sec * SEC_TO_MSEC + t.tv_nsec / MSEC_TO_NSEC;
1424 }
1425 
ParseHighlightQueryResult(const shared_ptr<ResultSet> & resultSet,ThumbnailData & data,int & err)1426 void ThumbnailUtils::ParseHighlightQueryResult(const shared_ptr<ResultSet> &resultSet, ThumbnailData &data, int &err)
1427 {
1428     int index;
1429     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, index);
1430     if (err == NativeRdb::E_OK) {
1431         ThumbnailRdbUtils::ParseStringResult(resultSet, index, data.id);
1432     }
1433 
1434     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_VIDEO_TRACKS, index);
1435     if (err == NativeRdb::E_OK) {
1436         ThumbnailRdbUtils::ParseStringResult(resultSet, index, data.tracks);
1437     }
1438 
1439     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_HIGHLIGHT_TRIGGER, index);
1440     if (err == NativeRdb::E_OK) {
1441         ThumbnailRdbUtils::ParseStringResult(resultSet, index, data.trigger);
1442     }
1443 }
1444 
ResizeThumb(int & width,int & height)1445 bool ThumbnailUtils::ResizeThumb(int &width, int &height)
1446 {
1447     int maxLen = max(width, height);
1448     int minLen = min(width, height);
1449     if (minLen == 0) {
1450         MEDIA_ERR_LOG("Divisor minLen is 0");
1451         return false;
1452     }
1453     double ratio = static_cast<double>(maxLen) / minLen;
1454     if (minLen > SHORT_SIDE_THRESHOLD) {
1455         minLen = SHORT_SIDE_THRESHOLD;
1456         maxLen = static_cast<int>(SHORT_SIDE_THRESHOLD * ratio);
1457         if (maxLen > MAXIMUM_SHORT_SIDE_THRESHOLD) {
1458             maxLen = MAXIMUM_SHORT_SIDE_THRESHOLD;
1459         }
1460         if (height > width) {
1461             width = minLen;
1462             height = maxLen;
1463         } else {
1464             width = maxLen;
1465             height = minLen;
1466         }
1467     }
1468     if (minLen <= SHORT_SIDE_THRESHOLD && maxLen > SHORT_SIDE_THRESHOLD && ratio > ASPECT_RATIO_THRESHOLD) {
1469         int newMaxLen = static_cast<int>(minLen * ASPECT_RATIO_THRESHOLD);
1470         if (height > width) {
1471             width = minLen;
1472             height = newMaxLen;
1473         } else {
1474             width = newMaxLen;
1475             height = minLen;
1476         }
1477     }
1478     return true;
1479 }
1480 
ResizeLcd(int & width,int & height)1481 bool ThumbnailUtils::ResizeLcd(int &width, int &height)
1482 {
1483     int maxLen = max(width, height);
1484     int minLen = min(width, height);
1485     if (minLen == 0) {
1486         MEDIA_ERR_LOG("Divisor minLen is 0");
1487         return false;
1488     }
1489     double ratio = static_cast<double>(maxLen) / minLen;
1490     if (std::abs(ratio) < EPSILON) {
1491         MEDIA_ERR_LOG("ratio is 0");
1492         return false;
1493     }
1494     int newMaxLen = maxLen;
1495     int newMinLen = minLen;
1496     if (maxLen > LCD_LONG_SIDE_THRESHOLD) {
1497         newMaxLen = LCD_LONG_SIDE_THRESHOLD;
1498         newMinLen = static_cast<int>(newMaxLen / ratio);
1499     }
1500     int lastMinLen = newMinLen;
1501     int lastMaxLen = newMaxLen;
1502     if (newMinLen < LCD_SHORT_SIDE_THRESHOLD && minLen >= LCD_SHORT_SIDE_THRESHOLD) {
1503         lastMinLen = LCD_SHORT_SIDE_THRESHOLD;
1504         lastMaxLen = static_cast<int>(lastMinLen * ratio);
1505         if (lastMaxLen > MAXIMUM_LCD_LONG_SIDE) {
1506             lastMaxLen = MAXIMUM_LCD_LONG_SIDE;
1507             lastMinLen = static_cast<int>(lastMaxLen / ratio);
1508         }
1509     }
1510 
1511     // When LCD size has changed after resize, check if width or height is odd number
1512     // Add one to the odd side to make sure LCD would be compressed through hardware encode
1513     if (max(width, height) != lastMaxLen) {
1514         lastMaxLen += lastMaxLen % EVEN_BASE_NUMBER;
1515         lastMinLen += lastMinLen % EVEN_BASE_NUMBER;
1516     }
1517     if (height > width) {
1518         width = lastMinLen;
1519         height = lastMaxLen;
1520     } else {
1521         width = lastMaxLen;
1522         height = lastMinLen;
1523     }
1524     return true;
1525 }
1526 
SaveAstcDataToKvStore(ThumbnailData & data,const ThumbnailType & type)1527 int ThumbnailUtils::SaveAstcDataToKvStore(ThumbnailData &data, const ThumbnailType &type)
1528 {
1529     string key;
1530     if (!MediaFileUtils::GenerateKvStoreKey(data.id, data.dateTaken, key)) {
1531         MEDIA_ERR_LOG("GenerateKvStoreKey failed");
1532         return E_ERR;
1533     }
1534 
1535     std::shared_ptr<MediaLibraryKvStore> kvStore;
1536     if (type == ThumbnailType::MTH_ASTC) {
1537         kvStore = MediaLibraryKvStoreManager::GetInstance()
1538             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
1539     } else if (type == ThumbnailType::YEAR_ASTC) {
1540         kvStore = MediaLibraryKvStoreManager::GetInstance()
1541             .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
1542     } else {
1543         MEDIA_ERR_LOG("invalid thumbnailType");
1544         return E_ERR;
1545     }
1546     CHECK_AND_RETURN_RET_LOG(kvStore != nullptr, E_ERR, "kvStore is nullptr");
1547 
1548     int status = kvStore->Insert(key, type == ThumbnailType::MTH_ASTC ? data.monthAstc : data.yearAstc);
1549     if (status != E_OK) {
1550         MEDIA_ERR_LOG("Insert failed, type:%{public}d, field_id:%{public}s, status:%{public}d",
1551             type, key.c_str(), status);
1552         return E_ERR;
1553     }
1554     MEDIA_INFO_LOG("type:%{public}d, field_id:%{public}s, status:%{public}d", type, key.c_str(), status);
1555     return status;
1556 }
1557 
CheckDateTaken(ThumbRdbOpt & opts,ThumbnailData & data)1558 bool ThumbnailUtils::CheckDateTaken(ThumbRdbOpt &opts, ThumbnailData &data)
1559 {
1560     if (!data.dateTaken.empty()) {
1561         return true;
1562     }
1563 
1564     vector<string> column = {
1565         MEDIA_DATA_DB_DATE_TAKEN,
1566     };
1567     vector<string> selectionArgs;
1568     string strQueryCondition = MEDIA_DATA_DB_ID + " = " + data.id;
1569     RdbPredicates rdbPredicates(opts.table);
1570     rdbPredicates.SetWhereClause(strQueryCondition);
1571     rdbPredicates.SetWhereArgs(selectionArgs);
1572     if (opts.store == nullptr) {
1573         MEDIA_ERR_LOG("opts.store is nullptr");
1574         return false;
1575     }
1576     shared_ptr<ResultSet> resultSet = opts.store->QueryByStep(rdbPredicates, column);
1577 
1578     int err;
1579     if (!ThumbnailRdbUtils::CheckResultSetCount(resultSet, err)) {
1580         MEDIA_ERR_LOG("CheckResultSetCount failed, err: %{public}d", err);
1581         return false;
1582     }
1583     err = resultSet->GoToFirstRow();
1584     CHECK_AND_RETURN_RET_LOG(err == E_OK, false, "GoToFirstRow failed, err: %{public}d", err);
1585 
1586     int index;
1587     err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_TAKEN, index);
1588     if (err == NativeRdb::E_OK) {
1589         ThumbnailRdbUtils::ParseStringResult(resultSet, index, data.dateTaken);
1590     } else {
1591         MEDIA_ERR_LOG("GetColumnIndex failed, err: %{public}d", err);
1592         resultSet->Close();
1593         return false;
1594     }
1595     resultSet->Close();
1596     return true;
1597 }
1598 
QueryThumbnailDataFromFileId(ThumbRdbOpt & opts,const std::string & id,ThumbnailData & data,int & err)1599 void ThumbnailUtils::QueryThumbnailDataFromFileId(ThumbRdbOpt &opts, const std::string &id,
1600     ThumbnailData &data, int &err)
1601 {
1602     if (opts.table.empty()) {
1603         MEDIA_ERR_LOG("Table is empty");
1604         return;
1605     }
1606     RdbPredicates predicates(opts.table);
1607     predicates.EqualTo(MediaColumn::MEDIA_ID, id);
1608     vector<string> columns = {
1609         MEDIA_DATA_DB_ID,
1610         MEDIA_DATA_DB_FILE_PATH,
1611         MEDIA_DATA_DB_HEIGHT,
1612         MEDIA_DATA_DB_WIDTH,
1613         MEDIA_DATA_DB_MEDIA_TYPE,
1614         MEDIA_DATA_DB_DATE_ADDED,
1615         MEDIA_DATA_DB_ORIENTATION,
1616         PhotoColumn::PHOTO_EXIF_ROTATE,
1617         MEDIA_DATA_DB_POSITION,
1618         MEDIA_DATA_DB_DATE_TAKEN,
1619         MEDIA_DATA_DB_DATE_MODIFIED,
1620         MEDIA_DATA_DB_DIRTY,
1621     };
1622 
1623     CHECK_AND_RETURN_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfo(opts.store, predicates, columns, data, err),
1624         "QueryThumbnailDataInfo failed, err:%{public}d", err);
1625 
1626     CHECK_AND_RETURN_LOG(err == NativeRdb::E_OK && !data.path.empty(),
1627         "Fail to query thumbnail data using id: %{public}s, err: %{public}d", id.c_str(), err);
1628     data.stats.uri = data.path;
1629 }
1630 
UpdateAstcDateTakenFromKvStore(ThumbRdbOpt & opts,const ThumbnailData & data)1631 bool ThumbnailUtils::UpdateAstcDateTakenFromKvStore(ThumbRdbOpt &opts, const ThumbnailData &data)
1632 {
1633     std::string formerKey;
1634     std::string newKey;
1635     if (!MediaFileUtils::GenerateKvStoreKey(opts.row, opts.dateTaken, formerKey) ||
1636         !MediaFileUtils::GenerateKvStoreKey(opts.row, data.dateTaken, newKey)) {
1637         MEDIA_ERR_LOG("UpdateAstcDateTakenFromKvStore GenerateKvStoreKey failed");
1638         return false;
1639     }
1640 
1641     std::shared_ptr<MediaLibraryKvStore> monthKvStore;
1642     std::shared_ptr<MediaLibraryKvStore> yearKvStore;
1643     monthKvStore = MediaLibraryKvStoreManager::GetInstance()
1644         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
1645     yearKvStore = MediaLibraryKvStoreManager::GetInstance()
1646         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
1647     if (monthKvStore == nullptr || yearKvStore == nullptr) {
1648         MEDIA_ERR_LOG("kvStore is nullptr");
1649         return false;
1650     }
1651 
1652     std::vector<uint8_t> monthValue;
1653     if (monthKvStore->Query(formerKey, monthValue) != E_OK || monthKvStore->Insert(newKey, monthValue) != E_OK) {
1654         MEDIA_ERR_LOG("MonthValue update failed, fileId %{public}s", opts.row.c_str());
1655         return false;
1656     }
1657     std::vector<uint8_t> yearValue;
1658     if (yearKvStore->Query(formerKey, yearValue) != E_OK || yearKvStore->Insert(newKey, yearValue) != E_OK) {
1659         MEDIA_ERR_LOG("YearValue update failed, fileId %{public}s", opts.row.c_str());
1660         return false;
1661     }
1662 
1663     int status = monthKvStore->Delete(formerKey) && yearKvStore->Delete(formerKey);
1664     CHECK_AND_RETURN_RET_LOG(status == E_OK, false, "Former kv delete failed, fileId %{public}s", opts.row.c_str());
1665     return true;
1666 }
1667 
GetThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & outData)1668 void ThumbnailUtils::GetThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &outData)
1669 {
1670     if (opts.store == nullptr) {
1671         return;
1672     }
1673     if (!opts.path.empty()) {
1674         outData.path = opts.path;
1675         outData.id = opts.row;
1676         outData.dateTaken = opts.dateTaken;
1677         outData.dateModified = opts.dateModified;
1678         outData.fileUri = opts.fileUri;
1679         outData.stats.uri = outData.fileUri;
1680         return;
1681     }
1682     string filesTableName = opts.table;
1683     int errCode = E_ERR;
1684     if (!opts.networkId.empty()) {
1685         filesTableName = opts.store->ObtainDistributedTableName(opts.networkId, opts.table, errCode);
1686     }
1687     if (filesTableName.empty()) {
1688         return;
1689     }
1690     opts.table = filesTableName;
1691     int err;
1692     ThumbnailUtils::QueryThumbnailInfo(opts, outData, err);
1693     if (err != E_OK) {
1694         MEDIA_ERR_LOG("query fail [%{public}d]", err);
1695     }
1696 }
1697 
ScaleThumbnailFromSource(ThumbnailData & data,const bool isSourceEx)1698 bool ThumbnailUtils::ScaleThumbnailFromSource(ThumbnailData &data, const bool isSourceEx)
1699 {
1700     std::shared_ptr<PixelMap> dataSource = isSourceEx ? data.source.GetPixelMapEx() : data.source.GetPixelMap();
1701     if (dataSource == nullptr) {
1702         MEDIA_ERR_LOG("Fail to scale thumbnail, data source is empty, isSourceEx: %{public}d.", isSourceEx);
1703         return false;
1704     }
1705     if (dataSource != nullptr && dataSource->IsHdr()) {
1706         uint32_t ret = dataSource->ToSdr();
1707         CHECK_AND_RETURN_RET_LOG(ret == E_OK, false, "Fail to transform to sdr, isSourceEx: %{public}d.", isSourceEx);
1708     }
1709     ImageInfo imageInfo;
1710     dataSource->GetImageInfo(imageInfo);
1711     if (imageInfo.pixelFormat != PixelFormat::RGBA_8888) {
1712         uint32_t ret = ImageFormatConvert::ConvertImageFormat(dataSource, PixelFormat::RGBA_8888);
1713         CHECK_AND_RETURN_RET_LOG(ret == E_OK, false,
1714             "Fail to scale convert image format, isSourceEx: %{public}d, format: %{public}d.",
1715             isSourceEx, imageInfo.pixelFormat);
1716     }
1717     if (isSourceEx) {
1718         data.source.SetPixelMapEx(dataSource);
1719     } else {
1720         data.source.SetPixelMap(dataSource);
1721     }
1722     Size desiredSize;
1723     Size targetSize = ConvertDecodeSize(data, {dataSource->GetWidth(), dataSource->GetHeight()}, desiredSize);
1724     if (!ScaleTargetPixelMap(dataSource, targetSize, Media::AntiAliasingOption::HIGH)) {
1725         MEDIA_ERR_LOG("Fail to scale to targetSize");
1726         return false;
1727     }
1728     if (!CenterScaleEx(dataSource, desiredSize, data.path)) {
1729         MEDIA_ERR_LOG("ScaleThumbnailFromSource center crop failed, path: %{public}s, isSourceEx: %{public}d.",
1730             DfxUtils::GetSafePath(data.path).c_str(), isSourceEx);
1731         return false;
1732     }
1733     return true;
1734 }
1735 
RecordStartGenerateStats(ThumbnailData::GenerateStats & stats,GenerateScene scene,LoadSourceType sourceType)1736 void ThumbnailUtils::RecordStartGenerateStats(ThumbnailData::GenerateStats &stats,
1737     GenerateScene scene, LoadSourceType sourceType)
1738 {
1739     stats.startTime = MediaFileUtils::UTCTimeMilliSeconds();
1740     stats.scene = scene;
1741     stats.sourceType = sourceType;
1742 }
1743 
RecordCostTimeAndReport(ThumbnailData::GenerateStats & stats)1744 void ThumbnailUtils::RecordCostTimeAndReport(ThumbnailData::GenerateStats &stats)
1745 {
1746     stats.totalCost = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - stats.startTime);
1747     DfxManager::GetInstance()->HandleThumbnailGeneration(stats);
1748 }
1749 
GetLocalThumbSize(const ThumbnailData & data,const ThumbnailType & type,Size & size)1750 bool ThumbnailUtils::GetLocalThumbSize(const ThumbnailData &data, const ThumbnailType& type, Size& size)
1751 {
1752     if (type != ThumbnailType::THUMB && type != ThumbnailType::LCD && type != ThumbnailType::THUMB_ASTC) {
1753         MEDIA_ERR_LOG("can not get size for such type: %{public}d", type);
1754         return false;
1755     }
1756     std::string tmpPath = "";
1757     switch (type) {
1758         case ThumbnailType::THUMB:
1759         case ThumbnailType::THUMB_ASTC:
1760             tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_THUMB_SUFFIX);
1761             break;
1762         case ThumbnailType::LCD:
1763             tmpPath = GetLocalThumbnailPath(data.path, THUMBNAIL_LCD_SUFFIX);
1764             break;
1765         default:
1766             break;
1767     }
1768     uint32_t err = 0;
1769     SourceOptions opts;
1770     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(tmpPath, opts, err);
1771     if (err != E_OK || imageSource == nullptr) {
1772         MEDIA_ERR_LOG("Failed to LoadImageSource for path:%{public}s", DfxUtils::GetSafePath(tmpPath).c_str());
1773         return false;
1774     }
1775     ImageInfo imageInfo;
1776     err = imageSource->GetImageInfo(0, imageInfo);
1777     CHECK_AND_RETURN_RET_LOG(err == E_OK, false,
1778         "Failed to Get ImageInfo, path:%{public}s", DfxUtils::GetSafePath(tmpPath).c_str());
1779     size.height = imageInfo.size.height;
1780     size.width = imageInfo.size.width;
1781     return true;
1782 }
1783 
SetThumbnailSizeValue(NativeRdb::ValuesBucket & values,Size & size,const std::string & column)1784 void ThumbnailUtils::SetThumbnailSizeValue(NativeRdb::ValuesBucket& values, Size& size, const std::string& column)
1785 {
1786     if (size.height == 0 || size.width == 0) {
1787         return;
1788     }
1789     std::string tmpSize = std::to_string(size.width) + ":" + std::to_string(size.height);
1790     values.PutString(column, tmpSize);
1791 }
1792 
IsMobileNetworkEnabled()1793 static bool IsMobileNetworkEnabled()
1794 {
1795     bool isWifiConnected = false;
1796     auto wifiDevicePtr = Wifi::WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
1797     if (wifiDevicePtr == nullptr) {
1798         MEDIA_ERR_LOG("wifiDevicePtr is null");
1799     } else {
1800         int32_t ret = wifiDevicePtr->IsConnected(isWifiConnected);
1801         if (ret != Wifi::WIFI_OPT_SUCCESS) {
1802             MEDIA_ERR_LOG("Get Is Connnected Fail: %{public}d", ret);
1803         }
1804     }
1805     if (isWifiConnected) {
1806         return true;
1807     }
1808     auto saMgr = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1809     CHECK_AND_RETURN_RET_LOG(saMgr != nullptr, false, "Failed to get SystemAbilityManagerClient");
1810     OHOS::sptr<OHOS::IRemoteObject> remoteObject = saMgr->CheckSystemAbility(STORAGE_MANAGER_MANAGER_ID);
1811     CHECK_AND_RETURN_RET_LOG(remoteObject != nullptr, false, "Token is null.");
1812     std::shared_ptr<DataShare::DataShareHelper> cloudHelper =
1813         DataShare::DataShareHelper::Creator(remoteObject, CLOUD_DATASHARE_URI);
1814     if (cloudHelper == nullptr) {
1815         MEDIA_INFO_LOG("cloudHelper is null");
1816         return false;
1817     }
1818     DataShare::DataSharePredicates predicates;
1819     predicates.EqualTo("key", "useMobileNetworkData");
1820     Uri cloudUri(CLOUD_DATASHARE_URI + "&key=useMobileNetworkData");
1821     vector<string> columns = {"value"};
1822     shared_ptr<DataShare::DataShareResultSet> resultSet =
1823         cloudHelper->Query(cloudUri, predicates, columns);
1824 
1825     //default mobile network is off
1826     string switchOn = "0";
1827     if (resultSet != nullptr && resultSet->GoToNextRow()==0) {
1828         resultSet->GetString(0, switchOn);
1829     }
1830     if (resultSet != nullptr) {
1831         resultSet->Close();
1832     }
1833     cloudHelper->Release();
1834     return switchOn == "1";
1835 }
1836 
QueryNoAstcInfosOnDemand(ThumbRdbOpt & opts,std::vector<ThumbnailData> & infos,NativeRdb::RdbPredicates & rdbPredicate,int & err)1837 bool ThumbnailUtils::QueryNoAstcInfosOnDemand(ThumbRdbOpt &opts,
1838     std::vector<ThumbnailData> &infos, NativeRdb::RdbPredicates &rdbPredicate, int &err)
1839 {
1840     vector<string> column = {
1841         MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_HEIGHT, MEDIA_DATA_DB_WIDTH,
1842         MEDIA_DATA_DB_POSITION, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_NAME,
1843         MEDIA_DATA_DB_ORIENTATION, PhotoColumn::PHOTO_EXIF_ROTATE, MEDIA_DATA_DB_DATE_TAKEN,
1844         MEDIA_DATA_DB_DATE_MODIFIED,
1845     };
1846     rdbPredicate.EqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "0");
1847     if (!IsMobileNetworkEnabled()) {
1848         rdbPredicate.BeginWrap();
1849         rdbPredicate.EqualTo(PhotoColumn::PHOTO_POSITION, "1");
1850         rdbPredicate.Or();
1851         rdbPredicate.EqualTo(PhotoColumn::PHOTO_POSITION, "3");
1852         rdbPredicate.EndWrap();
1853     }
1854     rdbPredicate.EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
1855     rdbPredicate.EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, "0");
1856     rdbPredicate.EqualTo(MEDIA_DATA_DB_DATE_TRASHED, "0");
1857     rdbPredicate.EqualTo(COMPAT_HIDDEN, "0");
1858     rdbPredicate.Limit(THUMBNAIL_GENERATE_BATCH_COUNT);
1859 
1860     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(opts.store, rdbPredicate, column, infos, err),
1861         false, "QueryThumbnailDataInfos failed, err:%{public}d", err);
1862     return true;
1863 }
1864 
ConvertStrToInt32(const std::string & str,int32_t & ret)1865 bool ThumbnailUtils::ConvertStrToInt32(const std::string &str, int32_t &ret)
1866 {
1867     if (str.empty() || str.length() > INT32_MAX_VALUE_LENGTH) {
1868         MEDIA_ERR_LOG("convert failed, str = %{public}s", str.c_str());
1869         return false;
1870     }
1871     if (!IsNumericStr(str)) {
1872         MEDIA_ERR_LOG("convert failed, input is not number, str = %{public}s", str.c_str());
1873         return false;
1874     }
1875     int64_t numberValue = std::stoll(str);
1876     if (numberValue < INT32_MIN || numberValue > INT32_MAX) {
1877         MEDIA_ERR_LOG("convert failed, Input is out of range, str = %{public}s", str.c_str());
1878         return false;
1879     }
1880     ret = static_cast<int32_t>(numberValue);
1881     return true;
1882 }
1883 
CheckCloudThumbnailDownloadFinish(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr)1884 bool ThumbnailUtils::CheckCloudThumbnailDownloadFinish(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr)
1885 {
1886     if (rdbStorePtr == nullptr) {
1887         MEDIA_ERR_LOG("RdbStorePtr is nullptr!");
1888         return false;
1889     }
1890 
1891     RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
1892     vector<string> column = { "count(1) AS count" };
1893     rdbPredicates.BeginWrap()
1894         ->GreaterThanOrEqualTo(PhotoColumn::PHOTO_POSITION, CLOUD_PHOTO_POSITION)
1895         ->And()
1896         ->NotEqualTo(PhotoColumn::PHOTO_THUMB_STATUS, CLOUD_THUMB_STATUS_DOWNLOAD)
1897         ->EndWrap();
1898     shared_ptr<ResultSet> resultSet = rdbStorePtr->Query(rdbPredicates, column);
1899     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1900         MEDIA_ERR_LOG("ResultSet is null!");
1901         return false;
1902     }
1903 
1904     int32_t count = GetInt32Val(RDB_QUERY_COUNT, resultSet);
1905     MEDIA_INFO_LOG("Number of undownloaded cloud images: %{public}d", count);
1906     if (count > CLOUD_THUMBNAIL_DOWNLOAD_FINISH_NUMBER) {
1907         return false;
1908     }
1909     return true;
1910 }
1911 
QueryOldKeyAstcInfos(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr,const std::string & table,std::vector<ThumbnailData> & infos)1912 bool ThumbnailUtils::QueryOldKeyAstcInfos(const std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr,
1913     const std::string &table, std::vector<ThumbnailData> &infos)
1914 {
1915     vector<string> column = {
1916         MEDIA_DATA_DB_ID,
1917         MEDIA_DATA_DB_DATE_ADDED,
1918         MEDIA_DATA_DB_DATE_TAKEN,
1919         MEDIA_DATA_DB_DATE_MODIFIED,
1920     };
1921     RdbPredicates rdbPredicates(table);
1922     rdbPredicates.GreaterThanOrEqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, "3");
1923     rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_TAKEN);
1924 
1925     CHECK_AND_RETURN_RET_LOG(ThumbnailRdbUtils::QueryThumbnailDataInfos(rdbStorePtr, rdbPredicates, column, infos),
1926         false, "QueryThumbnailDataInfos failed");
1927     return true;
1928 }
1929 
StoreThumbnailSize(const ThumbRdbOpt & opts,const ThumbnailData & data)1930 void ThumbnailUtils::StoreThumbnailSize(const ThumbRdbOpt& opts, const ThumbnailData& data)
1931 {
1932     std::string photoId = opts.row.empty() ? data.id : opts.row;
1933     std::string tmpPath = opts.path.empty() ? data.path : opts.path;
1934     if (tmpPath.find(ROOT_MEDIA_DIR + PHOTO_BUCKET) != string::npos) {
1935         MediaLibraryPhotoOperations::StoreThumbnailSize(photoId, tmpPath);
1936     }
1937 }
1938 
DropThumbnailSize(const ThumbRdbOpt & opts,const ThumbnailData & data)1939 void ThumbnailUtils::DropThumbnailSize(const ThumbRdbOpt& opts, const ThumbnailData& data)
1940 {
1941     std::string photoId = opts.row.empty() ? data.id : opts.row;
1942     std::string tmpPath = opts.path.empty() ? data.path : opts.path;
1943     if (tmpPath.find(ROOT_MEDIA_DIR + PHOTO_BUCKET) != string::npos) {
1944         MediaLibraryPhotoOperations::HasDroppedThumbnailSize(photoId);
1945     }
1946 }
1947 
BatchDropThumbnailSize(const ThumbnailDataBatch & dataBatch)1948 void ThumbnailUtils::BatchDropThumbnailSize(const ThumbnailDataBatch& dataBatch)
1949 {
1950     size_t dataBatchSize = dataBatch.ids.size();
1951     CHECK_AND_RETURN_LOG(dataBatchSize == dataBatch.paths.size(), "Failed to check dataBatch");
1952     vector<string> photoIds;
1953     for (size_t i = 0; i < dataBatchSize; i++) {
1954         if (dataBatch.paths[i].find(ROOT_MEDIA_DIR + PHOTO_BUCKET) != string::npos) {
1955             photoIds.push_back(dataBatch.ids[i]);
1956         }
1957     }
1958     MediaLibraryPhotoOperations::BatchDropThumbnailSize(photoIds);
1959 }
1960 
IsExCloudThumbnail(const ThumbnailData & data)1961 bool ThumbnailUtils::IsExCloudThumbnail(const ThumbnailData& data)
1962 {
1963     return ((data.exifRotate != 0 && data.exifRotate != static_cast<int32_t>(ExifRotateType::TOP_LEFT)) ||
1964         data.orientation != 0);
1965 }
1966 
HandleImageExifRotate(ThumbnailData & data)1967 void ThumbnailUtils::HandleImageExifRotate(ThumbnailData &data)
1968 {
1969     CHECK_AND_RETURN(data.exifRotate == 0 && data.mediaType == MediaType::MEDIA_TYPE_IMAGE);
1970     ExifRotateUtils::ConvertOrientationToExifRotate(data.orientation, data.exifRotate);
1971 }
1972 
NeedRotateThumbnail(const ThumbnailData & data)1973 bool ThumbnailUtils::NeedRotateThumbnail(const ThumbnailData& data)
1974 {
1975     return IsImageWithExifRotate(data) && !IsUseRotatedSource(data);
1976 }
1977 
IsImageWithExifRotate(const ThumbnailData & data)1978 bool ThumbnailUtils::IsImageWithExifRotate(const ThumbnailData& data)
1979 {
1980     return data.mediaType == MediaType::MEDIA_TYPE_IMAGE &&
1981         data.exifRotate != 0 && data.exifRotate != static_cast<int32_t>(ExifRotateType::TOP_LEFT);
1982 }
1983 
IsUseRotatedSource(const ThumbnailData & data)1984 bool ThumbnailUtils::IsUseRotatedSource(const ThumbnailData& data)
1985 {
1986     return data.lastLoadSource == SourceState::LOCAL_THUMB ||
1987         data.lastLoadSource == SourceState::LOCAL_LCD;
1988 }
1989 } // namespace Media
1990 } // namespace OHOS
1991