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