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