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