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