• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &degrees)
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 &degrees)
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 &degrees)
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