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