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