1 /*
2 * Copyright (C) 2022 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 #define MLOG_TAG "Thumbnail"
16
17 #include "thumbnail_utils.h"
18
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include "datashare_abs_result_set.h"
22 #include "device_manager.h"
23 #include "distributed_kv_data_manager.h"
24 #include "hitrace_meter.h"
25 #include "image_packer.h"
26 #include "medialibrary_common_utils.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_tracer.h"
29 #include "media_file_utils.h"
30 #include "media_log.h"
31 #include "parameter.h"
32 #include "rdb_errno.h"
33 #include "rdb_predicates.h"
34 #include "thumbnail_const.h"
35 #include "uri_helper.h"
36
37 using namespace std;
38 using namespace OHOS::DistributedKv;
39 using namespace OHOS::NativeRdb;
40
41 namespace OHOS {
42 namespace Media {
UpdateRemotePath(string & path,const string & networkId)43 bool ThumbnailUtils::UpdateRemotePath(string &path, const string &networkId)
44 {
45 MEDIA_DEBUG_LOG("ThumbnailUtils::UpdateRemotePath IN path = %{private}s, networkId = %{private}s",
46 path.c_str(), networkId.c_str());
47 if (path.empty() || networkId.empty()) {
48 return false;
49 }
50
51 size_t pos = path.find(MEDIA_DATA_DEVICE_PATH);
52 if (pos == string::npos) {
53 return false;
54 }
55
56 path.replace(pos, MEDIA_DATA_DEVICE_PATH.size(), networkId);
57 return true;
58 }
59
DeleteLcdData(ThumbRdbOpt & opts,ThumbnailData & thumbnailData)60 bool ThumbnailUtils::DeleteLcdData(ThumbRdbOpt &opts, ThumbnailData &thumbnailData)
61 {
62 if (thumbnailData.lcdKey.empty()) {
63 MEDIA_ERR_LOG("lcd Key is empty");
64 return false;
65 }
66
67 if (IsImageExist(thumbnailData.lcdKey, opts.networkId, opts.kvStore)) {
68 if (!RemoveDataFromKv(opts.kvStore, thumbnailData.lcdKey)) {
69 MEDIA_ERR_LOG("ThumbnailUtils::RemoveDataFromKv faild");
70 return false;
71 }
72 if (!CleanThumbnailInfo(opts, false, true)) {
73 return false;
74 }
75 }
76
77 return true;
78 }
79
DeleteDistributeLcdData(ThumbRdbOpt & opts,ThumbnailData & thumbnailData)80 bool ThumbnailUtils::DeleteDistributeLcdData(ThumbRdbOpt &opts, ThumbnailData &thumbnailData)
81 {
82 if (thumbnailData.lcdKey.empty()) {
83 MEDIA_ERR_LOG("lcd Key is empty");
84 return false;
85 }
86
87 if (IsImageExist(thumbnailData.lcdKey, opts.networkId, opts.kvStore)) {
88 if (!RemoveDataFromKv(opts.kvStore, thumbnailData.lcdKey)) {
89 MEDIA_ERR_LOG("ThumbnailUtils::RemoveDataFromKv faild");
90 return false;
91 }
92 if (!CleanDistributeLcdInfo(opts)) {
93 return false;
94 }
95 }
96
97 return true;
98 }
99
ClearThumbnailAllRecord(ThumbRdbOpt & opts,ThumbnailData & thumbnailData)100 bool ThumbnailUtils::ClearThumbnailAllRecord(ThumbRdbOpt &opts, ThumbnailData &thumbnailData)
101 {
102 if (IsImageExist(thumbnailData.lcdKey, opts.networkId, opts.kvStore)) {
103 if (!RemoveDataFromKv(opts.kvStore, thumbnailData.lcdKey)) {
104 MEDIA_ERR_LOG("ThumbnailUtils::RemoveDataFromKv faild");
105 return false;
106 }
107 }
108
109 if (IsImageExist(thumbnailData.thumbnailKey, opts.networkId, opts.kvStore)) {
110 if (!RemoveDataFromKv(opts.kvStore, thumbnailData.thumbnailKey)) {
111 MEDIA_ERR_LOG("ThumbnailUtils::RemoveDataFromKv faild");
112 return false;
113 }
114 }
115
116 if (!DeleteDistributeThumbnailInfo(opts)) {
117 return false;
118 }
119 return true;
120 }
121
LoadAudioFile(const string & path,shared_ptr<PixelMap> & pixelMap,float & degrees)122 bool ThumbnailUtils::LoadAudioFile(const string &path, shared_ptr<PixelMap> &pixelMap, float °rees)
123 {
124 std::shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
125 int32_t err = SetSource(avMetadataHelper, path);
126 if (err != E_OK) {
127 MEDIA_ERR_LOG("Av meta data helper set source failed %{public}d", err);
128 return false;
129 }
130
131 auto audioPicMemory = avMetadataHelper->FetchArtPicture();
132 if (audioPicMemory == nullptr) {
133 MEDIA_ERR_LOG("FetchArtPicture failed!");
134 return false;
135 }
136
137 SourceOptions opts;
138 uint32_t errCode = 0;
139 unique_ptr<ImageSource> audioImageSource = ImageSource::CreateImageSource(audioPicMemory->GetBase(),
140 audioPicMemory->GetSize(), opts, errCode);
141 if (audioImageSource == nullptr) {
142 MEDIA_ERR_LOG("Failed to create image source! path %{private}s errCode %{public}d",
143 path.c_str(), errCode);
144 return false;
145 }
146
147 errCode = 0;
148 DecodeOptions decOpts;
149 pixelMap = audioImageSource->CreatePixelMap(decOpts, errCode);
150 if (pixelMap == nullptr) {
151 MEDIA_ERR_LOG("Av meta data helper fetch frame at time failed");
152 return false;
153 }
154 if (pixelMap->GetAlphaType() == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
155 pixelMap->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
156 }
157 degrees = 0.0;
158 return true;
159 }
160
LoadVideoFile(const string & path,shared_ptr<PixelMap> & pixelMap,float & degrees)161 bool ThumbnailUtils::LoadVideoFile(const string &path, shared_ptr<PixelMap> &pixelMap, float °rees)
162 {
163 std::shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
164 int32_t err = SetSource(avMetadataHelper, path);
165 if (err != 0) {
166 MEDIA_ERR_LOG("Av meta data helper set source failed path %{private}s err %{public}d",
167 path.c_str(), err);
168 return false;
169 }
170 PixelMapParams param;
171 param.colorFormat = PixelFormat::RGBA_8888;
172 pixelMap = avMetadataHelper->FetchFrameAtTime(AV_FRAME_TIME,
173 AVMetadataQueryOption::AV_META_QUERY_NEXT_SYNC, param);
174 if (pixelMap == nullptr) {
175 MEDIA_ERR_LOG("Av meta data helper fetch frame at time failed");
176 return false;
177 }
178 if (pixelMap->GetAlphaType() == AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
179 pixelMap->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL);
180 }
181 std::string metaData = avMetadataHelper->ResolveMetadata(AV_KEY_VIDEO_ORIENTATION);
182 if (metaData == "") {
183 degrees = 0.0;
184 } else {
185 std::istringstream iss(metaData);
186 iss >> degrees;
187 }
188 return true;
189 }
190
LoadImageFile(const string & path,shared_ptr<PixelMap> & pixelMap,float & degrees)191 bool ThumbnailUtils::LoadImageFile(const string &path, shared_ptr<PixelMap> &pixelMap, float °rees)
192 {
193 uint32_t err = 0;
194 SourceOptions opts;
195
196 MediaLibraryTracer tracer;
197 tracer.Start("ImageSource::CreateImageSource");
198 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(path, opts, err);
199 if (err != E_OK) {
200 MEDIA_ERR_LOG("Failed to create image source path %{private}s err %{public}d",
201 path.c_str(), err);
202 return false;
203 }
204 tracer.Finish();
205 tracer.Start("imageSource->CreatePixelMap");
206
207 DecodeOptions decodeOpts;
208 pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
209 if (err != E_OK) {
210 MEDIA_ERR_LOG("Failed to create pixelmap path %{private}s err %{public}d",
211 path.c_str(), err);
212 return false;
213 }
214 int intTempMeta;
215 err = imageSource->GetImagePropertyInt(0, MEDIA_DATA_IMAGE_ORIENTATION, intTempMeta);
216 if (err != SUCCESS) {
217 degrees = 0.0;
218 } else {
219 degrees = static_cast<float>(intTempMeta);
220 }
221 return true;
222 }
223
GetUdid()224 std::string ThumbnailUtils::GetUdid()
225 {
226 static std::string innerUdid;
227
228 if (!innerUdid.empty()) {
229 return innerUdid;
230 }
231
232 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
233 OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
234 auto ret = deviceManager.GetLocalDeviceInfo(BUNDLE_NAME, deviceInfo);
235 if (ret != ERR_OK) {
236 MEDIA_ERR_LOG("get local device info failed, ret %{public}d", ret);
237 return std::string();
238 }
239
240 ret = deviceManager.GetUdidByNetworkId(BUNDLE_NAME, deviceInfo.networkId, innerUdid);
241 if (ret != 0) {
242 MEDIA_ERR_LOG("GetDeviceUdid error networkId = %{private}s, ret %{public}d",
243 deviceInfo.networkId, ret);
244 return std::string();
245 }
246 return innerUdid;
247 }
248
GenKey(ThumbnailData & data,std::string & key)249 bool ThumbnailUtils::GenKey(ThumbnailData &data, std::string &key)
250 {
251 MediaLibraryTracer tracer;
252 tracer.Start("GenerateKey");
253 if (data.hashKey.empty()) {
254 std::string sourceKey = GetUdid() + data.path + to_string(data.dateModified);
255 MEDIA_DEBUG_LOG("ThumbnailUtils::GenKey sourceKey %{private}s", sourceKey.c_str());
256 int32_t ret = MediaLibraryCommonUtils::GenKeySHA256(sourceKey, data.hashKey);
257 if (ret != E_OK) {
258 MEDIA_ERR_LOG("MediaLibraryThumbnail::Failed to GenKey, err: %{public}d", ret);
259 return false;
260 }
261 }
262 key = data.hashKey + data.suffix;
263
264 MEDIA_DEBUG_LOG("GenKey OUT [%{public}s]", key.c_str());
265 return true;
266 }
267
GenThumbnailKey(ThumbnailData & data)268 bool ThumbnailUtils::GenThumbnailKey(ThumbnailData &data)
269 {
270 data.suffix = THUMBNAIL_END_SUFFIX;
271 return GenKey(data, data.thumbnailKey);
272 }
273
GenLcdKey(ThumbnailData & data)274 bool ThumbnailUtils::GenLcdKey(ThumbnailData &data)
275 {
276 data.suffix = THUMBNAIL_LCD_END_SUFFIX;
277 return GenKey(data, data.lcdKey);
278 }
279
280
CompressImage(std::shared_ptr<PixelMap> & pixelMap,const Size & size,std::vector<uint8_t> & data,float degrees)281 bool ThumbnailUtils::CompressImage(std::shared_ptr<PixelMap> &pixelMap, const Size &size,
282 std::vector<uint8_t> &data, float degrees)
283 {
284 MediaLibraryTracer tracer;
285 tracer.Start("PixelMap::Create");
286 InitializationOptions opts = {
287 .size = size,
288 .pixelFormat = PixelFormat::BGRA_8888,
289 .alphaType = AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL,
290 .scaleMode = ScaleMode::CENTER_CROP
291 };
292
293 unique_ptr<PixelMap> compressImage = PixelMap::Create(*pixelMap, opts);
294 tracer.Finish();
295 if (compressImage == nullptr) {
296 MEDIA_ERR_LOG("Failed to create compressImage");
297 return false;
298 }
299
300 PackOption option = {
301 .format = THUMBNAIL_FORMAT,
302 .quality = THUMBNAIL_QUALITY,
303 .numberHint = NUMBER_HINT_1
304 };
305 compressImage->rotate(degrees);
306 data.resize(compressImage->GetByteCount());
307 tracer.Start("imagePacker.StartPacking");
308 ImagePacker imagePacker;
309 uint32_t err = imagePacker.StartPacking(data.data(), data.size(), option);
310 tracer.Finish();
311 if (err != E_OK) {
312 MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
313 return false;
314 }
315
316 tracer.Start("imagePacker.AddImage");
317 err = imagePacker.AddImage(*compressImage);
318 tracer.Finish();
319 if (err != E_OK) {
320 MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
321 return false;
322 }
323
324 tracer.Start("imagePacker.FinalizePacking");
325 int64_t packedSize = 0;
326 err = imagePacker.FinalizePacking(packedSize);
327 if (err != E_OK) {
328 MEDIA_ERR_LOG("Failed to StartPacking %{public}d", err);
329 return false;
330 }
331
332 data.resize(packedSize);
333 return true;
334 }
335
SaveImage(const shared_ptr<SingleKvStore> & kvStore,const string & key,const vector<uint8_t> & image)336 Status ThumbnailUtils::SaveImage(const shared_ptr<SingleKvStore> &kvStore, const string &key,
337 const vector<uint8_t> &image)
338 {
339 MEDIA_DEBUG_LOG("ThumbnailUtils::SaveImage IN key [%{public}s]", key.c_str());
340 Status status = Status::ERROR;
341 if (kvStore == nullptr) {
342 MEDIA_ERR_LOG("KvStore is not init");
343 return status;
344 }
345
346 MediaLibraryTracer tracer;
347 tracer.Start("SaveImage kvStore->Put");
348 Value val(image);
349 status = kvStore->Put(key, val);
350 return status;
351 }
352
QueryThumbnailSet(ThumbRdbOpt & opts)353 shared_ptr<AbsSharedResultSet> ThumbnailUtils::QueryThumbnailSet(ThumbRdbOpt &opts)
354 {
355 MEDIA_DEBUG_LOG("ThumbnailUtils::QueryThumbnailSet IN row [%{public}s]", opts.row.c_str());
356 vector<string> column = {
357 MEDIA_DATA_DB_ID,
358 MEDIA_DATA_DB_FILE_PATH,
359 MEDIA_DATA_DB_THUMBNAIL,
360 MEDIA_DATA_DB_LCD,
361 MEDIA_DATA_DB_MEDIA_TYPE,
362 MEDIA_DATA_DB_DATE_MODIFIED
363 };
364
365 vector<string> selectionArgs;
366 string strQueryCondition = MEDIA_DATA_DB_ID + " = " + opts.row;
367
368 RdbPredicates rdbPredicates(opts.table);
369 rdbPredicates.SetWhereClause(strQueryCondition);
370 rdbPredicates.SetWhereArgs(selectionArgs);
371 shared_ptr<AbsSharedResultSet> resultSet = opts.store->Query(rdbPredicates, column);
372 return resultSet;
373 }
374
QueryThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)375 shared_ptr<AbsSharedResultSet> ThumbnailUtils::QueryThumbnailInfo(ThumbRdbOpt &opts,
376 ThumbnailData &data, int &err)
377 {
378 MediaLibraryTracer tracer;
379 tracer.Start("QueryThumbnailInfo");
380 shared_ptr<AbsSharedResultSet> resultSet = QueryThumbnailSet(opts);
381 if (!CheckResultSetCount(resultSet, err)) {
382 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
383 return nullptr;
384 }
385
386 if (!CheckResultSetColumn(resultSet, err)) {
387 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
388 return nullptr;
389 }
390
391 ThumbnailRdbData rdbData;
392 ParseQueryResult(resultSet, rdbData, err);
393 ThumbnailDataCopy(data, rdbData);
394 return resultSet;
395 }
396
QueryLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)397 bool ThumbnailUtils::QueryLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
398 {
399 vector<string> column = {
400 MEDIA_DATA_DB_ID,
401 };
402 RdbPredicates rdbPredicates(opts.table);
403 rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
404 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
405 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
406 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
407 if (resultSet == nullptr) {
408 MEDIA_ERR_LOG("query failed");
409 return false;
410 }
411 int rowCount = 0;
412 err = resultSet->GetRowCount(rowCount);
413 resultSet.reset();
414 if (err != E_OK) {
415 MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
416 return false;
417 }
418 MEDIA_DEBUG_LOG("rowCount is %{public}d", rowCount);
419 if (rowCount <= 0) {
420 MEDIA_INFO_LOG("No match! %{public}s", rdbPredicates.ToString().c_str());
421 rowCount = 0;
422 }
423
424 outLcdCount = rowCount;
425 return true;
426 }
427
QueryDistributeLcdCount(ThumbRdbOpt & opts,int & outLcdCount,int & err)428 bool ThumbnailUtils::QueryDistributeLcdCount(ThumbRdbOpt &opts, int &outLcdCount, int &err)
429 {
430 vector<string> column = {
431 REMOTE_THUMBNAIL_DB_ID,
432 };
433 RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
434 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
435 rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
436 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
437 if (resultSet == nullptr) {
438 MEDIA_ERR_LOG("query failed");
439 return false;
440 }
441 int rowCount = 0;
442 err = resultSet->GetRowCount(rowCount);
443 resultSet.reset();
444 if (err != E_OK) {
445 MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
446 return false;
447 }
448 MEDIA_INFO_LOG("rowCount is %{public}d", rowCount);
449 if (rowCount <= 0) {
450 MEDIA_INFO_LOG("No match! %{public}s", rdbPredicates.ToString().c_str());
451 rowCount = 0;
452 }
453 outLcdCount = rowCount;
454 return true;
455 }
456
QueryHasLcdFiles(ThumbRdbOpt & opts,vector<ThumbnailRdbData> & infos,int & err)457 bool ThumbnailUtils::QueryHasLcdFiles(ThumbRdbOpt &opts, vector<ThumbnailRdbData> &infos, int &err)
458 {
459 vector<string> column = {
460 MEDIA_DATA_DB_ID,
461 MEDIA_DATA_DB_FILE_PATH,
462 MEDIA_DATA_DB_THUMBNAIL,
463 MEDIA_DATA_DB_LCD,
464 MEDIA_DATA_DB_MEDIA_TYPE,
465 MEDIA_DATA_DB_DATE_MODIFIED
466 };
467 RdbPredicates rdbPredicates(opts.table);
468 rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
469 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
470 if (!CheckResultSetCount(resultSet, err)) {
471 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
472 return false;
473 }
474
475 if (!CheckResultSetColumn(resultSet, err)) {
476 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
477 return false;
478 }
479
480 do {
481 ThumbnailRdbData data;
482 ParseQueryResult(resultSet, data, err);
483 if (!data.path.empty()) {
484 infos.push_back(data);
485 }
486 } while (resultSet->GoToNextRow() == E_OK);
487
488 resultSet.reset();
489 return true;
490 }
491
QueryHasThumbnailFiles(ThumbRdbOpt & opts,vector<ThumbnailRdbData> & infos,int & err)492 bool ThumbnailUtils::QueryHasThumbnailFiles(ThumbRdbOpt &opts, vector<ThumbnailRdbData> &infos, int &err)
493 {
494 vector<string> column = {
495 MEDIA_DATA_DB_ID,
496 MEDIA_DATA_DB_FILE_PATH,
497 MEDIA_DATA_DB_THUMBNAIL,
498 MEDIA_DATA_DB_LCD,
499 MEDIA_DATA_DB_MEDIA_TYPE,
500 MEDIA_DATA_DB_DATE_MODIFIED
501 };
502 RdbPredicates rdbPredicates(opts.table);
503 rdbPredicates.IsNotNull(MEDIA_DATA_DB_THUMBNAIL);
504 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
505 if (!CheckResultSetCount(resultSet, err)) {
506 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
507 return false;
508 }
509
510 if (!CheckResultSetColumn(resultSet, err)) {
511 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
512 return false;
513 }
514
515 do {
516 ThumbnailRdbData data;
517 ParseQueryResult(resultSet, data, err);
518 if (!data.path.empty()) {
519 infos.push_back(data);
520 }
521 } while (resultSet->GoToNextRow() == E_OK);
522
523 resultSet.reset();
524 return true;
525 }
526
QueryAgingDistributeLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailRdbData> & infos,int & err)527 bool ThumbnailUtils::QueryAgingDistributeLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
528 vector<ThumbnailRdbData> &infos, int &err)
529 {
530 vector<string> column = {
531 REMOTE_THUMBNAIL_DB_FILE_ID,
532 MEDIA_DATA_DB_LCD
533 };
534 RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
535 rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
536 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
537
538 rdbPredicates.Limit(LcdLimit);
539 rdbPredicates.OrderByAsc(MEDIA_DATA_DB_TIME_VISIT);
540 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
541 if (!CheckResultSetCount(resultSet, err)) {
542 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
543 return false;
544 }
545
546 if (!CheckResultSetColumn(resultSet, err)) {
547 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
548 return false;
549 }
550
551 do {
552 ThumbnailRdbData data;
553 ParseQueryResult(resultSet, data, err);
554 if (!data.lcdKey.empty()) {
555 infos.push_back(data);
556 }
557 } while (resultSet->GoToNextRow() == E_OK);
558
559 resultSet.reset();
560 return true;
561 }
562
QueryAgingLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailRdbData> & infos,int & err)563 bool ThumbnailUtils::QueryAgingLcdInfos(ThumbRdbOpt &opts, int LcdLimit,
564 vector<ThumbnailRdbData> &infos, int &err)
565 {
566 vector<string> column = {
567 MEDIA_DATA_DB_ID,
568 MEDIA_DATA_DB_FILE_PATH,
569 MEDIA_DATA_DB_THUMBNAIL,
570 MEDIA_DATA_DB_LCD,
571 MEDIA_DATA_DB_MEDIA_TYPE,
572 MEDIA_DATA_DB_DATE_MODIFIED
573 };
574 RdbPredicates rdbPredicates(opts.table);
575 rdbPredicates.IsNotNull(MEDIA_DATA_DB_LCD);
576 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
577 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
578
579 rdbPredicates.Limit(LcdLimit);
580 rdbPredicates.OrderByAsc(MEDIA_DATA_DB_TIME_VISIT);
581 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
582 if (!CheckResultSetCount(resultSet, err)) {
583 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
584 return false;
585 }
586
587 if (!CheckResultSetColumn(resultSet, err)) {
588 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
589 return false;
590 }
591
592 do {
593 ThumbnailRdbData data;
594 ParseQueryResult(resultSet, data, err);
595 if (!data.path.empty()) {
596 infos.push_back(data);
597 }
598 } while (resultSet->GoToNextRow() == E_OK);
599
600 resultSet.reset();
601 return true;
602 }
603
QueryNoLcdInfos(ThumbRdbOpt & opts,int LcdLimit,vector<ThumbnailRdbData> & infos,int & err)604 bool ThumbnailUtils::QueryNoLcdInfos(ThumbRdbOpt &opts, int LcdLimit, vector<ThumbnailRdbData> &infos, int &err)
605 {
606 vector<string> column = {
607 MEDIA_DATA_DB_ID,
608 MEDIA_DATA_DB_FILE_PATH,
609 MEDIA_DATA_DB_THUMBNAIL,
610 MEDIA_DATA_DB_LCD,
611 MEDIA_DATA_DB_MEDIA_TYPE,
612 MEDIA_DATA_DB_DATE_MODIFIED
613 };
614 RdbPredicates rdbPredicates(opts.table);
615 rdbPredicates.IsNull(MEDIA_DATA_DB_LCD);
616 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
617 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
618 rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
619
620 rdbPredicates.Limit(LcdLimit);
621 rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
622 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
623 if (!CheckResultSetCount(resultSet, err)) {
624 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
625 return false;
626 }
627
628 if (!CheckResultSetColumn(resultSet, err)) {
629 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
630 return false;
631 }
632
633 do {
634 ThumbnailRdbData data;
635 ParseQueryResult(resultSet, data, err);
636 if (!data.path.empty()) {
637 infos.push_back(data);
638 }
639 } while (resultSet->GoToNextRow() == E_OK);
640
641 resultSet.reset();
642 return true;
643 }
644
QueryNoThumbnailInfos(ThumbRdbOpt & opts,vector<ThumbnailRdbData> & infos,int & err)645 bool ThumbnailUtils::QueryNoThumbnailInfos(ThumbRdbOpt &opts, vector<ThumbnailRdbData> &infos, int &err)
646 {
647 vector<string> column = {
648 MEDIA_DATA_DB_ID,
649 MEDIA_DATA_DB_FILE_PATH,
650 MEDIA_DATA_DB_THUMBNAIL,
651 MEDIA_DATA_DB_LCD,
652 MEDIA_DATA_DB_MEDIA_TYPE,
653 MEDIA_DATA_DB_DATE_MODIFIED
654 };
655 RdbPredicates rdbPredicates(opts.table);
656 rdbPredicates.IsNull(MEDIA_DATA_DB_THUMBNAIL);
657 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_FILE));
658 rdbPredicates.NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM));
659 rdbPredicates.EqualTo(MEDIA_DATA_DB_IS_TRASH, "0");
660
661 rdbPredicates.Limit(THUMBNAIL_QUERY_MAX);
662 rdbPredicates.OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
663
664 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
665 if (!CheckResultSetCount(resultSet, err)) {
666 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
667 if (err == E_EMPTY_VALUES_BUCKET) {
668 return true;
669 }
670 return false;
671 }
672
673 if (!CheckResultSetColumn(resultSet, err)) {
674 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
675 return false;
676 }
677
678 do {
679 ThumbnailRdbData data;
680 ParseQueryResult(resultSet, data, err);
681 if (!data.path.empty()) {
682 infos.push_back(data);
683 }
684 } while (resultSet->GoToNextRow() == E_OK);
685 resultSet.reset();
686 return true;
687 }
688
UpdateThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)689 bool ThumbnailUtils::UpdateThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
690 {
691 ValuesBucket values;
692 int changedRows;
693 if (data.thumbnailKey.empty() && data.lcdKey.empty()) {
694 MEDIA_ERR_LOG("No key to update!");
695 return false;
696 }
697
698 if (!data.thumbnailKey.empty()) {
699 values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
700 }
701
702 if (!data.lcdKey.empty()) {
703 values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
704 int64_t timeNow = UTCTimeSeconds();
705 values.PutLong(MEDIA_DATA_DB_TIME_VISIT, timeNow);
706 }
707
708 MediaLibraryTracer tracer;
709 tracer.Start("UpdateThumbnailInfo opts.store->Update");
710 err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
711 vector<string> { opts.row });
712 if (err != NativeRdb::E_OK) {
713 MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
714 return false;
715 }
716 std::vector<std::string> devices;
717 opts.table = MEDIALIBRARY_TABLE;
718 SyncPushTable(opts, devices);
719 return true;
720 }
721
UpdateVisitTime(ThumbRdbOpt & opts,ThumbnailData & data,int & err)722 bool ThumbnailUtils::UpdateVisitTime(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
723 {
724 if (!opts.networkId.empty()) {
725 return DoUpdateRemoteThumbnail(opts, data, err);
726 }
727
728 ValuesBucket values;
729 int changedRows;
730 int64_t timeNow = UTCTimeSeconds();
731 values.PutLong(MEDIA_DATA_DB_TIME_VISIT, timeNow);
732 err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
733 vector<string> { opts.row });
734 if (err != NativeRdb::E_OK) {
735 MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
736 return false;
737 }
738 return true;
739 }
740
QueryDeviceThumbnailRecords(ThumbRdbOpt & opts,std::vector<ThumbnailRdbData> & infos,int & err)741 bool ThumbnailUtils::QueryDeviceThumbnailRecords(ThumbRdbOpt &opts, std::vector<ThumbnailRdbData> &infos,
742 int &err)
743 {
744 vector<string> column = {
745 REMOTE_THUMBNAIL_DB_FILE_ID,
746 MEDIA_DATA_DB_THUMBNAIL,
747 MEDIA_DATA_DB_LCD
748 };
749 RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
750 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, opts.udid);
751 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
752 if (!CheckResultSetCount(resultSet, err)) {
753 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
754 return false;
755 }
756
757 if (!CheckResultSetColumn(resultSet, err)) {
758 MEDIA_ERR_LOG("CheckResultSetColumn failed %{public}d", err);
759 return false;
760 }
761
762 ThumbnailRdbData data;
763 do {
764 ParseQueryResult(resultSet, data, err);
765 infos.push_back(data);
766 } while (resultSet->GoToNextRow() == E_OK);
767
768 resultSet.reset();
769 return true;
770 }
771
GetRemoteThumbnailInfo(ThumbRdbOpt & opts,const std::string & id,const std::string & udid,int & err)772 bool ThumbnailUtils::GetRemoteThumbnailInfo(ThumbRdbOpt &opts, const std::string &id,
773 const std::string &udid, int &err)
774 {
775 vector<string> column = {
776 REMOTE_THUMBNAIL_DB_ID
777 };
778 RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
779 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, id);
780 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, udid);
781 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
782 if (!CheckResultSetCount(resultSet, err)) {
783 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
784 return false;
785 }
786 resultSet.reset();
787 return true;
788 }
789
GetUdidByNetworkId(ThumbRdbOpt & opts,const std::string & networkId,std::string & outUdid,int & err)790 bool ThumbnailUtils::GetUdidByNetworkId(ThumbRdbOpt &opts, const std::string &networkId,
791 std::string &outUdid, int &err)
792 {
793 vector<string> column = {
794 DEVICE_DB_ID,
795 DEVICE_DB_UDID
796 };
797 RdbPredicates rdbPredicates(DEVICE_TABLE);
798 rdbPredicates.EqualTo(DEVICE_DB_NETWORK_ID, networkId);
799 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
800 if (!CheckResultSetCount(resultSet, err)) {
801 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
802 return false;
803 }
804
805 err = resultSet->GoToFirstRow();
806 if (err != E_OK) {
807 MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
808 return false;
809 }
810 int index;
811 err = resultSet->GetColumnIndex(DEVICE_DB_UDID, index);
812 if (err == NativeRdb::E_OK) {
813 ParseStringResult(resultSet, index, outUdid, err);
814 } else {
815 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", DEVICE_DB_UDID.c_str(), err);
816 }
817 return true;
818 }
819
QueryRemoteThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int & err)820 bool ThumbnailUtils::QueryRemoteThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
821 {
822 if (data.udid.empty() && !GetUdidByNetworkId(opts, opts.networkId, data.udid, err)) {
823 MEDIA_ERR_LOG("GetUdidByNetworkId failed! %{public}d", err);
824 return false;
825 }
826
827 vector<string> column = {
828 REMOTE_THUMBNAIL_DB_ID,
829 MEDIA_DATA_DB_THUMBNAIL,
830 MEDIA_DATA_DB_LCD
831 };
832 RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
833 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, data.id);
834 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, data.udid);
835 shared_ptr<ResultSet> resultSet = opts.store->Query(rdbPredicates, column);
836 if (!CheckResultSetCount(resultSet, err)) {
837 MEDIA_ERR_LOG("CheckResultSetCount failed %{public}d", err);
838 return false;
839 }
840
841 err = resultSet->GoToFirstRow();
842 if (err != E_OK) {
843 MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
844 return false;
845 }
846
847 int index;
848 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_LCD, index);
849 if (err == NativeRdb::E_OK) {
850 ParseStringResult(resultSet, index, data.lcdKey, err);
851 }
852
853 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_THUMBNAIL, index);
854 if (err == NativeRdb::E_OK) {
855 ParseStringResult(resultSet, index, data.thumbnailKey, err);
856 }
857 return true;
858 }
859
IsKeyNotSame(const string & newKey,const string & oldKey)860 static inline bool IsKeyNotSame(const string &newKey, const string &oldKey)
861 {
862 if (!newKey.empty() && !oldKey.empty() && (newKey != oldKey)) {
863 return true;
864 }
865 return false;
866 }
867
DoUpdateRemoteThumbnail(ThumbRdbOpt & opts,ThumbnailData & data,int & err)868 bool ThumbnailUtils::DoUpdateRemoteThumbnail(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
869 {
870 if (opts.networkId.empty()) {
871 return false;
872 }
873 if (data.thumbnailKey.empty() && data.lcdKey.empty()) {
874 return false;
875 }
876 ThumbnailData tmpData = data;
877 auto isGot = ThumbnailUtils::QueryRemoteThumbnail(opts, tmpData, err);
878 if (isGot) {
879 if (IsKeyNotSame(data.thumbnailKey, tmpData.thumbnailKey)) {
880 if (!RemoveDataFromKv(opts.kvStore, tmpData.thumbnailKey)) {
881 return false;
882 }
883 }
884 if (IsKeyNotSame(data.lcdKey, tmpData.lcdKey)) {
885 if (!RemoveDataFromKv(opts.kvStore, tmpData.lcdKey)) {
886 return false;
887 }
888 }
889 }
890
891 data.udid = tmpData.udid;
892 if (isGot) {
893 return UpdateRemoteThumbnailInfo(opts, data, err);
894 } else {
895 return InsertRemoteThumbnailInfo(opts, data, err);
896 }
897 }
898
UpdateRemoteThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)899 bool ThumbnailUtils::UpdateRemoteThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
900 {
901 RdbPredicates rdbPredicates(REMOTE_THUMBNAIL_TABLE);
902 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_FILE_ID, data.id);
903 rdbPredicates.EqualTo(REMOTE_THUMBNAIL_DB_UDID, data.udid);
904
905 ValuesBucket values;
906 if (!data.thumbnailKey.empty()) {
907 values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
908 }
909
910 if (!data.lcdKey.empty()) {
911 values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
912 int64_t timeNow = UTCTimeSeconds();
913 values.PutLong(MEDIA_DATA_DB_TIME_VISIT, timeNow);
914 }
915
916 int changedRows;
917 err = opts.store->Update(changedRows, values, rdbPredicates);
918 if (err != NativeRdb::E_OK) {
919 MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
920 return false;
921 }
922
923 return true;
924 }
925
InsertRemoteThumbnailInfo(ThumbRdbOpt & opts,ThumbnailData & data,int & err)926 bool ThumbnailUtils::InsertRemoteThumbnailInfo(ThumbRdbOpt &opts, ThumbnailData &data, int &err)
927 {
928 ValuesBucket values;
929 values.PutInt(REMOTE_THUMBNAIL_DB_FILE_ID, std::stoi(data.id));
930 values.PutString(REMOTE_THUMBNAIL_DB_UDID, data.udid);
931 if (!data.thumbnailKey.empty()) {
932 values.PutString(MEDIA_DATA_DB_THUMBNAIL, data.thumbnailKey);
933 }
934
935 if (!data.lcdKey.empty()) {
936 values.PutString(MEDIA_DATA_DB_LCD, data.lcdKey);
937 int64_t timeNow = UTCTimeSeconds();
938 values.PutLong(MEDIA_DATA_DB_TIME_VISIT, timeNow);
939 }
940
941 int64_t outRowId = -1;
942 err = opts.store->Insert(outRowId, REMOTE_THUMBNAIL_TABLE, values);
943 if (err != NativeRdb::E_OK) {
944 MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
945 return false;
946 }
947 return true;
948 }
949
CleanThumbnailInfo(ThumbRdbOpt & opts,bool withThumb,bool withLcd)950 bool ThumbnailUtils::CleanThumbnailInfo(ThumbRdbOpt &opts, bool withThumb, bool withLcd)
951 {
952 ValuesBucket values;
953 if (withThumb) {
954 values.PutNull(MEDIA_DATA_DB_THUMBNAIL);
955 }
956 if (withLcd) {
957 values.PutNull(MEDIA_DATA_DB_LCD);
958 values.PutLong(MEDIA_DATA_DB_TIME_VISIT, 0);
959 }
960 int changedRows;
961 auto err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?",
962 vector<string> { opts.row });
963 if (err != NativeRdb::E_OK) {
964 MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
965 return false;
966 }
967 return true;
968 }
969
CleanDistributeLcdInfo(ThumbRdbOpt & opts)970 bool ThumbnailUtils::CleanDistributeLcdInfo(ThumbRdbOpt &opts)
971 {
972 string udid;
973 int err;
974 if (!GetUdidByNetworkId(opts, opts.networkId, udid, err)) {
975 MEDIA_ERR_LOG("GetUdidByNetworkId failed! %{public}d", err);
976 return false;
977 }
978
979 ValuesBucket values;
980 values.PutNull(MEDIA_DATA_DB_LCD);
981 values.PutLong(MEDIA_DATA_DB_TIME_VISIT, 0);
982 int changedRows;
983 vector<string> whereArgs = { udid, opts.row };
984 string deleteCondition = REMOTE_THUMBNAIL_DB_UDID + " = ? AND " +
985 REMOTE_THUMBNAIL_DB_FILE_ID + " = ?";
986 auto ret = opts.store->Update(changedRows, REMOTE_THUMBNAIL_TABLE, values, deleteCondition, whereArgs);
987 if (ret != NativeRdb::E_OK) {
988 MEDIA_ERR_LOG("RdbStore Delete failed! %{public}d", ret);
989 return false;
990 }
991 return true;
992 }
993
DeleteDistributeThumbnailInfo(ThumbRdbOpt & opts)994 bool ThumbnailUtils::DeleteDistributeThumbnailInfo(ThumbRdbOpt &opts)
995 {
996 int changedRows;
997 vector<string> whereArgs = { opts.udid, opts.row };
998 string deleteCondition = REMOTE_THUMBNAIL_DB_UDID + " = ? AND " +
999 REMOTE_THUMBNAIL_DB_FILE_ID + " = ?";
1000 auto err = opts.store->Delete(changedRows, REMOTE_THUMBNAIL_TABLE, deleteCondition, whereArgs);
1001 if (err != NativeRdb::E_OK) {
1002 MEDIA_ERR_LOG("RdbStore Delete failed! %{public}d", err);
1003 return false;
1004 }
1005 return true;
1006 }
1007
LoadSourceImage(ThumbnailData & data)1008 bool ThumbnailUtils::LoadSourceImage(ThumbnailData &data)
1009 {
1010 if (data.source != nullptr) {
1011 return true;
1012 }
1013 MediaLibraryTracer tracer;
1014 tracer.Start("LoadSourceImage");
1015
1016 bool ret = false;
1017 if (data.mediaType == MEDIA_TYPE_VIDEO) {
1018 ret = LoadVideoFile(data.path, data.source, data.degrees);
1019 } else if (data.mediaType == MEDIA_TYPE_AUDIO) {
1020 ret = LoadAudioFile(data.path, data.source, data.degrees);
1021 } else {
1022 ret = LoadImageFile(data.path, data.source, data.degrees);
1023 }
1024
1025 return ret;
1026 }
1027
CreateThumbnailData(ThumbnailData & data)1028 bool ThumbnailUtils::CreateThumbnailData(ThumbnailData &data)
1029 {
1030 Size size = { DEFAULT_THUMBNAIL_SIZE, DEFAULT_THUMBNAIL_SIZE };
1031 MediaLibraryTracer tracer;
1032 tracer.Start("CompressImage");
1033 bool ret = CompressImage(data.source, size, data.thumbnail, data.degrees);
1034 return ret;
1035 }
1036
CreateLcdData(ThumbnailData & data,int32_t lcdSize)1037 bool ThumbnailUtils::CreateLcdData(ThumbnailData &data, int32_t lcdSize)
1038 {
1039 lcdSize = (lcdSize == 0) ? DEFAULT_LCD_SIZE : lcdSize;
1040 auto width = data.source->GetWidth();
1041 auto height = data.source->GetHeight();
1042 int32_t maxSize = 1;
1043 maxSize = max(maxSize, max(width, height));
1044 double scale = 1.0f;
1045 if (lcdSize < maxSize) {
1046 scale = (float) lcdSize / maxSize;
1047 }
1048 Size size = {
1049 static_cast<int32_t> (scale * width),
1050 static_cast<int32_t> (scale * height),
1051 };
1052
1053 MediaLibraryTracer tracer;
1054 tracer.Start("CompressImage");
1055 bool ret = CompressImage(data.source, size, data.lcd, data.degrees);
1056 return ret;
1057 }
1058
SaveThumbnailData(ThumbnailData & data,const std::string & networkId,const shared_ptr<SingleKvStore> & kvStore)1059 Status ThumbnailUtils::SaveThumbnailData(ThumbnailData &data, const std::string &networkId,
1060 const shared_ptr<SingleKvStore> &kvStore)
1061 {
1062 Status status = SaveImage(kvStore, data.thumbnailKey, data.thumbnail);
1063 if (status != DistributedKv::Status::SUCCESS) {
1064 MEDIA_ERR_LOG("SaveImage failed! status %{public}d", status);
1065 return status;
1066 }
1067 if (!networkId.empty()) {
1068 MediaLibraryTracer tracer;
1069 tracer.Start("SaveThumbnailData::SyncPushKvstore");
1070 auto syncStatus = SyncPushKvstore(kvStore, data.thumbnailKey, networkId);
1071 if (syncStatus != DistributedKv::Status::SUCCESS) {
1072 MEDIA_ERR_LOG("SyncPushKvstore failed! ret %{public}d", syncStatus);
1073 return syncStatus;
1074 }
1075 }
1076
1077 return status;
1078 }
1079
SaveLcdData(ThumbnailData & data,const std::string & networkId,const shared_ptr<SingleKvStore> & kvStore)1080 Status ThumbnailUtils::SaveLcdData(ThumbnailData &data, const std::string &networkId,
1081 const shared_ptr<SingleKvStore> &kvStore)
1082 {
1083 Status status = SaveImage(kvStore, data.lcdKey, data.lcd);
1084 if (status != DistributedKv::Status::SUCCESS) {
1085 MEDIA_ERR_LOG("SaveLcdData SaveImage failed! status %{public}d", status);
1086 return status;
1087 }
1088 if (!networkId.empty()) {
1089 MediaLibraryTracer tracer;
1090 tracer.Start("SaveLcdData::SyncPushKvstore");
1091 auto syncStatus = SyncPushKvstore(kvStore, data.lcdKey, networkId);
1092 if (syncStatus != DistributedKv::Status::SUCCESS) {
1093 MEDIA_ERR_LOG("SaveLcdData SyncPushKvstore failed! ret %{public}d", syncStatus);
1094 return syncStatus;
1095 }
1096 }
1097 return status;
1098 }
1099
SetSource(std::shared_ptr<AVMetadataHelper> avMetadataHelper,const std::string & path)1100 int32_t ThumbnailUtils::SetSource(std::shared_ptr<AVMetadataHelper> avMetadataHelper, const std::string &path)
1101 {
1102 if (avMetadataHelper == nullptr) {
1103 MEDIA_ERR_LOG("avMetadataHelper == nullptr");
1104 return E_ERR;
1105 }
1106 MEDIA_DEBUG_LOG("path = %{private}s", path.c_str());
1107 UriHelper uriHelper(path);
1108 if ((uriHelper.UriType() != UriHelper::URI_TYPE_FILE) && !uriHelper.AccessCheck(UriHelper::URI_READ)) {
1109 MEDIA_ERR_LOG("Invalid file Path %{private}s", path.c_str());
1110 return E_ERR;
1111 }
1112 std::string rawFile = uriHelper.FormattedUri();
1113 rawFile = rawFile.substr(strlen("file://"));
1114 int32_t fd = open(rawFile.c_str(), O_RDONLY);
1115 if (fd < 0) {
1116 MEDIA_ERR_LOG("Open file failed, err %{public}d", errno);
1117 return E_ERR;
1118 }
1119
1120 struct stat64 st;
1121 if (fstat64(fd, &st) != 0) {
1122 MEDIA_ERR_LOG("Get file state failed, err %{public}d", errno);
1123 (void)close(fd);
1124 return E_ERR;
1125 }
1126 int64_t length = static_cast<int64_t>(st.st_size);
1127 int32_t ret = avMetadataHelper->SetSource(fd, 0, length, 1);
1128 if (ret != 0) {
1129 MEDIA_ERR_LOG("SetSource fail");
1130 (void)close(fd);
1131 return E_ERR;
1132 }
1133 (void)close(fd);
1134 return SUCCESS;
1135 }
1136
SyncPushTable(ThumbRdbOpt & opts,std::vector<std::string> & devices,bool isBlock)1137 bool ThumbnailUtils::SyncPushTable(ThumbRdbOpt &opts, std::vector<std::string> &devices, bool isBlock)
1138 {
1139 MEDIA_DEBUG_LOG("SyncPushTable table = %{public}s", opts.table.c_str());
1140 // start sync
1141 DistributedRdb::SyncOption option;
1142 option.mode = DistributedRdb::SyncMode::PUSH;
1143 option.isBlock = isBlock;
1144
1145 NativeRdb::AbsRdbPredicates predicate(opts.table);
1146 (devices.size() > 0) ? predicate.InDevices(devices) : predicate.InAllDevices();
1147
1148 DistributedRdb::SyncCallback callback = [](const DistributedRdb::SyncResult& syncResult) {
1149 // update device db
1150 for (auto iter = syncResult.begin(); iter != syncResult.end(); iter++) {
1151 if (iter->first.empty()) {
1152 MEDIA_ERR_LOG("SyncPushTable deviceId is empty");
1153 continue;
1154 }
1155 if (iter->second != 0) {
1156 MEDIA_ERR_LOG("SyncPushTable device = %{private}s syncResult = %{private}d",
1157 iter->first.c_str(), iter->second);
1158 continue;
1159 }
1160 MEDIA_ERR_LOG("SyncPushTable device = %{private}s success", iter->first.c_str());
1161 }
1162 };
1163
1164 StartTrace(HITRACE_TAG_FILEMANAGEMENT, "SyncPushTable rdbStore->Sync");
1165 int ret = opts.store->Sync(option, predicate, callback);
1166 FinishTrace(HITRACE_TAG_FILEMANAGEMENT);
1167
1168 return ret == E_OK;
1169 }
1170
SyncPullTable(ThumbRdbOpt & opts,std::vector<std::string> & devices,bool isBlock)1171 bool ThumbnailUtils::SyncPullTable(ThumbRdbOpt &opts, std::vector<std::string> &devices, bool isBlock)
1172 {
1173 MEDIA_DEBUG_LOG("SyncPullTable table = %{public}s", opts.table.c_str());
1174 DistributedRdb::SyncOption option;
1175 option.mode = DistributedRdb::SyncMode::PULL;
1176 option.isBlock = isBlock;
1177
1178 NativeRdb::AbsRdbPredicates predicate(opts.table);
1179 (devices.size() > 0) ? predicate.InDevices(devices) : predicate.InAllDevices();
1180 if (!opts.row.empty()) {
1181 predicate.EqualTo(MEDIA_DATA_DB_ID, opts.row);
1182 }
1183
1184 shared_ptr<SyncStatus> status = make_shared<SyncStatus>();
1185 DistributedRdb::SyncCallback callback = [status](const DistributedRdb::SyncResult& syncResult) {
1186 for (auto iter = syncResult.begin(); iter != syncResult.end(); iter++) {
1187 if (iter->second != 0) {
1188 MEDIA_ERR_LOG("SyncPullTable device = %{private}s syncResult = %{private}d",
1189 iter->first.c_str(), iter->second);
1190 continue;
1191 }
1192 std::unique_lock<std::mutex> lock(status->mtx_);
1193 status->isSyncComplete_ = true;
1194 }
1195 status->cond_.notify_one();
1196 };
1197
1198 MediaLibraryTracer tracer;
1199 tracer.Start("SyncPullTable rdbStore->Sync");
1200 int ret = opts.store->Sync(option, predicate, callback);
1201 if (ret != E_OK || !isBlock) {
1202 return ret == E_OK;
1203 }
1204
1205 std::unique_lock<std::mutex> lock(status->mtx_);
1206 bool success = status->cond_.wait_for(lock, std::chrono::milliseconds(WAIT_FOR_MS),
1207 [status] { return status->isSyncComplete_; });
1208 if (success) {
1209 MEDIA_DEBUG_LOG("wait_for SyncCompleted");
1210 } else {
1211 MEDIA_INFO_LOG("wait_for timeout");
1212 }
1213
1214 return true;
1215 }
1216
SyncPullKvstore(const shared_ptr<SingleKvStore> & kvStore,const string key,const string & networkId)1217 Status ThumbnailUtils::SyncPullKvstore(const shared_ptr<SingleKvStore> &kvStore, const string key,
1218 const string &networkId)
1219 {
1220 MEDIA_DEBUG_LOG("networkId is %{private}s key is %{private}s",
1221 networkId.c_str(), key.c_str());
1222 if (kvStore == nullptr) {
1223 MEDIA_ERR_LOG("kvStore is null");
1224 return DistributedKv::Status::ERROR;
1225 }
1226 if (networkId.empty()) {
1227 MEDIA_ERR_LOG("networkId empty error");
1228 return DistributedKv::Status::ERROR;
1229 }
1230
1231 DataQuery dataQuery;
1232 dataQuery.KeyPrefix(key);
1233 dataQuery.Limit(1, 0); // for force to sync single key
1234 std::vector<std::string> deviceIds = { networkId };
1235 MediaLibraryTracer tracer;
1236 tracer.Start("SyncPullKvstore kvStore->SyncPull");
1237 auto callback = std::make_shared<MediaLibrarySyncCallback>();
1238 Status status = kvStore->Sync(deviceIds, OHOS::DistributedKv::SyncMode::PULL, dataQuery, callback);
1239 if (!callback->WaitFor()) {
1240 MEDIA_DEBUG_LOG("wait_for timeout");
1241 status = Status::ERROR;
1242 }
1243 return status;
1244 }
1245
SyncPushKvstore(const shared_ptr<SingleKvStore> & kvStore,string key,const string & networkId)1246 Status ThumbnailUtils::SyncPushKvstore(const shared_ptr<SingleKvStore> &kvStore, string key, const string &networkId)
1247 {
1248 MEDIA_DEBUG_LOG("networkId is %{private}s", networkId.c_str());
1249 if (kvStore == nullptr) {
1250 MEDIA_ERR_LOG("kvStore is null");
1251 return Status::ERROR;
1252 }
1253 if (networkId.empty()) {
1254 MEDIA_ERR_LOG("networkId empty error");
1255 return Status::ERROR;
1256 }
1257 DistributedKv::DataQuery dataQuery;
1258 dataQuery.KeyPrefix(key);
1259 vector<string> deviceIds = { networkId };
1260 MediaLibraryTracer tracer;
1261 tracer.Start("SyncPushKvstore kvStore->SyncPush");
1262 return kvStore->Sync(deviceIds, OHOS::DistributedKv::SyncMode::PUSH, dataQuery);
1263 }
1264
ResizeImage(const vector<uint8_t> & data,const Size & size,unique_ptr<PixelMap> & pixelMap)1265 bool ThumbnailUtils::ResizeImage(const vector<uint8_t> &data, const Size &size, unique_ptr<PixelMap> &pixelMap)
1266 {
1267 MediaLibraryTracer tracer;
1268 tracer.Start("ResizeImage");
1269 if (data.size() == 0) {
1270 MEDIA_ERR_LOG("Data is empty");
1271 return false;
1272 }
1273
1274 tracer.Start("ImageSource::CreateImageSource");
1275 uint32_t err = E_OK;
1276 SourceOptions opts;
1277 unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(data.data(),
1278 data.size(), opts, err);
1279 if (err != E_OK) {
1280 MEDIA_ERR_LOG("Failed to create image source %{public}d", err);
1281 return false;
1282 }
1283 tracer.Finish();
1284
1285 tracer.Start("imageSource->CreatePixelMap");
1286 DecodeOptions decodeOpts;
1287 decodeOpts.desiredSize.width = size.width;
1288 decodeOpts.desiredSize.height = size.height;
1289 pixelMap = imageSource->CreatePixelMap(decodeOpts, err);
1290 if (err != Media::SUCCESS) {
1291 MEDIA_ERR_LOG("Failed to create pixelmap %{public}d", err);
1292 return false;
1293 }
1294
1295 return true;
1296 }
1297
GetKvResultSet(const shared_ptr<SingleKvStore> & kvStore,const string & key,const std::string & networkId,shared_ptr<DataShare::ResultSetBridge> & outResultSet)1298 bool ThumbnailUtils::GetKvResultSet(const shared_ptr<SingleKvStore> &kvStore, const string &key,
1299 const std::string &networkId, shared_ptr<DataShare::ResultSetBridge> &outResultSet)
1300 {
1301 if (key.empty()) {
1302 MEDIA_ERR_LOG("key empty");
1303 return false;
1304 }
1305
1306 if (kvStore == nullptr) {
1307 MEDIA_ERR_LOG("KvStore is not init");
1308 return false;
1309 }
1310
1311 MediaLibraryTracer tracer;
1312 tracer.Start("GetKey kvStore->Get");
1313 shared_ptr<SingleKvStore> singleKv = kvStore;
1314 outResultSet = shared_ptr<DataShare::ResultSetBridge>(ThumbnailDataShareBridge::Create(singleKv, key));
1315 return true;
1316 }
1317
RemoveDataFromKv(const shared_ptr<SingleKvStore> & kvStore,const string & key)1318 bool ThumbnailUtils::RemoveDataFromKv(const shared_ptr<SingleKvStore> &kvStore, const string &key)
1319 {
1320 if (key.empty()) {
1321 MEDIA_ERR_LOG("RemoveLcdFromKv key empty");
1322 return false;
1323 }
1324
1325 if (kvStore == nullptr) {
1326 MEDIA_ERR_LOG("KvStore is not init");
1327 return false;
1328 }
1329
1330 MediaLibraryTracer tracer;
1331 tracer.Start("RemoveLcdFromKv kvStore->Get");
1332 auto status = kvStore->Delete(key);
1333 if (status != Status::SUCCESS) {
1334 MEDIA_ERR_LOG("Failed to get key [%{public}s] ret [%{public}d]", key.c_str(), status);
1335 return false;
1336 }
1337 return true;
1338 }
1339
DeleteOriginImage(ThumbRdbOpt & opts,ThumbnailData & thumbnailData)1340 bool ThumbnailUtils::DeleteOriginImage(ThumbRdbOpt &opts, ThumbnailData &thumbnailData)
1341 {
1342 ThumbnailData tmpData;
1343 int err = 0;
1344 auto rdbSet = QueryThumbnailInfo(opts, tmpData, err);
1345 if (rdbSet == nullptr) {
1346 MEDIA_ERR_LOG("QueryThumbnailInfo Faild [ %{public}d ]", err);
1347 return false;
1348 }
1349
1350 if (IsKeyNotSame(tmpData.thumbnailKey, thumbnailData.thumbnailKey)) {
1351 if (!ThumbnailUtils::RemoveDataFromKv(opts.kvStore, tmpData.thumbnailKey)) {
1352 MEDIA_ERR_LOG("DeleteThumbnailData Faild");
1353 return false;
1354 }
1355 }
1356 if (IsKeyNotSame(tmpData.lcdKey, thumbnailData.lcdKey)) {
1357 if (!ThumbnailUtils::RemoveDataFromKv(opts.kvStore, tmpData.lcdKey)) {
1358 MEDIA_ERR_LOG("DeleteLCDlData Faild");
1359 return false;
1360 }
1361 }
1362 return true;
1363 }
1364
IsImageExist(const string & key,const string & networkId,const shared_ptr<SingleKvStore> & kvStore)1365 bool ThumbnailUtils::IsImageExist(const string &key, const string &networkId, const shared_ptr<SingleKvStore> &kvStore)
1366 {
1367 if (key.empty()) {
1368 return false;
1369 }
1370
1371 if (kvStore == nullptr) {
1372 MEDIA_ERR_LOG("KvStore is not init");
1373 return false;
1374 }
1375
1376 bool ret = false;
1377 DataQuery query;
1378 query.InKeys({key});
1379 int count = 0;
1380 auto status = kvStore->GetCount(query, count);
1381 if (status == Status::SUCCESS && count > 0) {
1382 MEDIA_DEBUG_LOG("kvStore_->GetCount key [%{public}s] status %{public}d", key.c_str(), status);
1383 ret = true;
1384 }
1385
1386 if (!ret) {
1387 MEDIA_DEBUG_LOG("IsImageExist failed!, key [%{public}s]", key.c_str());
1388 if (!networkId.empty()) {
1389 MediaLibraryTracer tracer;
1390 tracer.Start("SyncPullKvstore");
1391 auto syncStatus = SyncPullKvstore(kvStore, key, networkId);
1392 if (syncStatus == DistributedKv::Status::SUCCESS) {
1393 MEDIA_DEBUG_LOG("SyncPullKvstore SUCCESS");
1394 return true;
1395 } else {
1396 MEDIA_ERR_LOG("SyncPullKvstore failed! ret %{public}d", syncStatus);
1397 return false;
1398 }
1399 }
1400 }
1401 return ret;
1402 }
1403
ThumbnailDataCopy(ThumbnailData & data,ThumbnailRdbData & rdbData)1404 void ThumbnailUtils::ThumbnailDataCopy(ThumbnailData &data, ThumbnailRdbData &rdbData)
1405 {
1406 data.id = rdbData.id;
1407 data.path = rdbData.path;
1408 data.thumbnailKey = rdbData.thumbnailKey;
1409 data.lcdKey = rdbData.lcdKey;
1410 data.mediaType = rdbData.mediaType;
1411 data.dateModified = rdbData.dateModified;
1412 }
1413
UTCTimeSeconds()1414 int64_t ThumbnailUtils::UTCTimeSeconds()
1415 {
1416 struct timespec t;
1417 t.tv_sec = 0;
1418 t.tv_nsec = 0;
1419 clock_gettime(CLOCK_REALTIME, &t);
1420 return (int64_t)(t.tv_sec);
1421 }
1422
CheckResultSetCount(const shared_ptr<ResultSet> & resultSet,int & err)1423 bool ThumbnailUtils::CheckResultSetCount(const shared_ptr<ResultSet> &resultSet, int &err)
1424 {
1425 if (resultSet == nullptr) {
1426 return false;
1427 }
1428 int rowCount = 0;
1429 err = resultSet->GetRowCount(rowCount);
1430 if (err != E_OK) {
1431 MEDIA_ERR_LOG("Failed to get row count %{public}d", err);
1432 return false;
1433 }
1434
1435 if (rowCount <= 0) {
1436 MEDIA_ERR_LOG("CheckCount No match!");
1437 err = E_EMPTY_VALUES_BUCKET;
1438 return false;
1439 }
1440
1441 return true;
1442 }
1443
CheckResultSetColumn(const shared_ptr<ResultSet> & resultSet,int & err)1444 bool ThumbnailUtils::CheckResultSetColumn(const shared_ptr<ResultSet> &resultSet, int &err)
1445 {
1446 if (resultSet == nullptr) {
1447 return false;
1448 }
1449 err = resultSet->GoToFirstRow();
1450 if (err != E_OK) {
1451 MEDIA_ERR_LOG("Failed GoToFirstRow %{public}d", err);
1452 return false;
1453 }
1454
1455 int columnCount = 0;
1456 err = resultSet->GetColumnCount(columnCount);
1457 if (err != E_OK) {
1458 MEDIA_ERR_LOG("Failed to get column count %{public}d", err);
1459 return false;
1460 }
1461
1462 if (columnCount <= 0) {
1463 MEDIA_ERR_LOG("No column!");
1464 err = E_EMPTY_VALUES_BUCKET;
1465 return false;
1466 }
1467
1468 return true;
1469 }
1470
ParseStringResult(const shared_ptr<ResultSet> & resultSet,int index,string & data,int & err)1471 void ThumbnailUtils::ParseStringResult(const shared_ptr<ResultSet> &resultSet, int index, string &data, int &err)
1472 {
1473 bool isNull = true;
1474 err = resultSet->IsColumnNull(index, isNull);
1475 if (err != E_OK) {
1476 MEDIA_ERR_LOG("Failed to check column %{public}d null %{public}d", index, err);
1477 }
1478
1479 if (!isNull) {
1480 err = resultSet->GetString(index, data);
1481 if (err != E_OK) {
1482 MEDIA_ERR_LOG("Failed to get column %{public}d string %{public}d", index, err);
1483 }
1484 }
1485 }
1486
ParseQueryResult(const shared_ptr<ResultSet> & resultSet,ThumbnailRdbData & data,int & err)1487 void ThumbnailUtils::ParseQueryResult(const shared_ptr<ResultSet> &resultSet, ThumbnailRdbData &data, int &err)
1488 {
1489 int index;
1490 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, index);
1491 if (err == NativeRdb::E_OK) {
1492 ParseStringResult(resultSet, index, data.id, err);
1493 } else {
1494 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", MEDIA_DATA_DB_ID.c_str(), err);
1495 }
1496
1497 err = resultSet->GetColumnIndex(REMOTE_THUMBNAIL_DB_FILE_ID, index);
1498 if (err == NativeRdb::E_OK) {
1499 ParseStringResult(resultSet, index, data.id, err);
1500 } else {
1501 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", MEDIA_DATA_DB_ID.c_str(), err);
1502 }
1503
1504 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_FILE_PATH, index);
1505 if (err == NativeRdb::E_OK) {
1506 ParseStringResult(resultSet, index, data.path, err);
1507 } else {
1508 MEDIA_ERR_LOG("Get column %{private}s index error %{private}d", MEDIA_DATA_DB_FILE_PATH.c_str(), err);
1509 }
1510
1511 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_THUMBNAIL, index);
1512 if (err == NativeRdb::E_OK) {
1513 ParseStringResult(resultSet, index, data.thumbnailKey, err);
1514 } else {
1515 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", MEDIA_DATA_DB_THUMBNAIL.c_str(), err);
1516 }
1517
1518 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_LCD, index);
1519 if (err == NativeRdb::E_OK) {
1520 ParseStringResult(resultSet, index, data.lcdKey, err);
1521 } else {
1522 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", MEDIA_DATA_DB_LCD.c_str(), err);
1523 }
1524
1525 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_MEDIA_TYPE, index);
1526 if (err == NativeRdb::E_OK) {
1527 data.mediaType = MediaType::MEDIA_TYPE_ALL;
1528 err = resultSet->GetInt(index, data.mediaType);
1529 } else {
1530 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", MEDIA_DATA_DB_MEDIA_TYPE.c_str(), err);
1531 }
1532
1533 err = resultSet->GetColumnIndex(MEDIA_DATA_DB_DATE_MODIFIED, index);
1534 if (err == NativeRdb::E_OK) {
1535 err = resultSet->GetLong(index, data.dateModified);
1536 } else {
1537 MEDIA_ERR_LOG("Get column %{public}s index error %{public}d", MEDIA_DATA_DB_DATE_MODIFIED.c_str(), err);
1538 }
1539 }
1540
SyncCompleted(const map<std::string,DistributedKv::Status> & results)1541 void MediaLibrarySyncCallback::SyncCompleted(const map<std::string, DistributedKv::Status> &results)
1542 {
1543 for (auto &item : results) {
1544 if (item.second == Status::SUCCESS) {
1545 MEDIA_DEBUG_LOG("ThumbnailUtils::SyncCompleted OK");
1546 std::unique_lock<std::mutex> lock(status_.mtx_);
1547 status_.isSyncComplete_ = true;
1548 break;
1549 }
1550 }
1551 status_.cond_.notify_one();
1552 }
1553
WaitFor()1554 bool MediaLibrarySyncCallback::WaitFor()
1555 {
1556 std::unique_lock<std::mutex> lock(status_.mtx_);
1557 bool ret = status_.cond_.wait_for(lock, std::chrono::milliseconds(WAIT_FOR_MS),
1558 [this]() { return status_.isSyncComplete_; });
1559 if (!ret) {
1560 MEDIA_INFO_LOG("ThumbnailUtils::SyncPullKvstore wait_for timeout");
1561 } else {
1562 MEDIA_DEBUG_LOG("ThumbnailUtils::SyncPullKvstore wait_for SyncCompleted");
1563 }
1564 return ret;
1565 }
1566 } // namespace Media
1567 } // namespace OHOS
1568