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_service.h"
18 
19 #include "display_manager.h"
20 #include "ipc_skeleton.h"
21 #include "ithumbnail_helper.h"
22 #include "media_column.h"
23 #include "media_file_utils.h"
24 #include "medialibrary_async_worker.h"
25 #include "medialibrary_db_const.h"
26 #include "medialibrary_errno.h"
27 #include "medialibrary_kvstore_manager.h"
28 #include "medialibrary_photo_operations.h"
29 #include "medialibrary_type_const.h"
30 #include "medialibrary_unistore_manager.h"
31 #include "media_log.h"
32 #include "result_set_utils.h"
33 #include "thumbnail_aging_helper.h"
34 #include "thumbnail_const.h"
35 #include "thumbnail_generate_helper.h"
36 #include "thumbnail_generate_worker_manager.h"
37 #include "thumbnail_uri_utils.h"
38 #include "post_event_utils.h"
39 
40 using namespace std;
41 using namespace OHOS::DistributedKv;
42 using namespace OHOS::NativeRdb;
43 using namespace OHOS::AbilityRuntime;
44 
45 namespace OHOS {
46 namespace Media {
47 std::shared_ptr<ThumbnailService> ThumbnailService::thumbnailServiceInstance_{nullptr};
48 std::mutex ThumbnailService::instanceLock_;
ThumbnailService(void)49 ThumbnailService::ThumbnailService(void)
50 {
51     rdbStorePtr_ = nullptr;
52 #ifdef DISTRIBUTED
53     kvStorePtr_ = nullptr;
54 #endif
55 }
56 
GetInstance()57 shared_ptr<ThumbnailService> ThumbnailService::GetInstance()
58 {
59     if (thumbnailServiceInstance_ == nullptr) {
60         std::lock_guard<std::mutex> lockGuard(instanceLock_);
61         if (thumbnailServiceInstance_ != nullptr) {
62             return thumbnailServiceInstance_;
63         }
64         thumbnailServiceInstance_ = shared_ptr<ThumbnailService>(new ThumbnailService());
65     }
66 
67     return thumbnailServiceInstance_;
68 }
69 
GetDefaultWindowSize(Size &size)70 static bool GetDefaultWindowSize(Size &size)
71 {
72     auto &displayMgr = OHOS::Rosen::DisplayManager::GetInstance();
73     auto display = displayMgr.GetDefaultDisplay();
74     if (display == nullptr) {
75         MEDIA_ERR_LOG("Get display window size failed");
76         return false;
77     }
78     size.width = display->GetWidth();
79     size.height = display->GetHeight();
80     if (size.width <= 0) {
81         MEDIA_WARN_LOG("Get Default display width is invalid %{public}d", size.width);
82         size.width = DEFAULT_LCD_SIZE;
83     }
84     if (size.height <= 0) {
85         MEDIA_WARN_LOG("Get Default display height is invalid %{public}d", size.height);
86         size.height = DEFAULT_LCD_SIZE;
87     }
88     MEDIA_INFO_LOG("display window size::w %{public}d, h %{public}d", size.width, size.height);
89 
90     return true;
91 }
92 
CheckSizeValid()93 bool ThumbnailService::CheckSizeValid()
94 {
95     if (!isScreenSizeInit_) {
96         if (!GetDefaultWindowSize(screenSize_)) {
97             return false;
98         }
99         isScreenSizeInit_ = true;
100     }
101     return true;
102 }
103 
UpdateAstcInfo(ThumbRdbOpt &opts, std::string id)104 static void UpdateAstcInfo(ThumbRdbOpt &opts, std::string id)
105 {
106     if (id.empty()) {
107         return;
108     }
109 
110     ValuesBucket values;
111     int changedRows;
112     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, MediaFileUtils::UTCTimeMilliSeconds());
113     int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?", vector<string> { id });
114     if (err != NativeRdb::E_OK) {
115         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
116     }
117 }
118 
Init(const shared_ptr<RdbStore> &rdbStore, const shared_ptr<SingleKvStore> &kvStore, const shared_ptr<Context> &context)119 void ThumbnailService::Init(const shared_ptr<RdbStore> &rdbStore,
120 #ifdef DISTRIBUTED
121     const shared_ptr<SingleKvStore> &kvStore,
122 #endif
123     const shared_ptr<Context> &context)
124 {
125     rdbStorePtr_ = rdbStore;
126 #ifdef DISTRIBUTED
127     kvStorePtr_ = kvStore;
128 #endif
129     context_ = context;
130 
131     if (!GetDefaultWindowSize(screenSize_)) {
132         MEDIA_ERR_LOG("GetDefaultWindowSize failed");
133     } else {
134         isScreenSizeInit_ = true;
135     }
136 }
137 
ReleaseService()138 void ThumbnailService::ReleaseService()
139 {
140     StopAllWorker();
141     rdbStorePtr_ = nullptr;
142 #ifdef DISTRIBUTED
143     kvStorePtr_ = nullptr;
144 #endif
145     context_ = nullptr;
146     thumbnailServiceInstance_ = nullptr;
147 }
148 
149 #ifdef MEDIALIBRARY_COMPATIBILITY
GetPathFromDb(const shared_ptr<NativeRdb::RdbStore> &rdbStorePtr, const string &fileId, const string &table, string &path)150 static int32_t GetPathFromDb(const shared_ptr<NativeRdb::RdbStore> &rdbStorePtr, const string &fileId,
151     const string &table, string &path)
152 {
153     if (rdbStorePtr == nullptr) {
154         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
155             {KEY_OPT_TYPE, OptType::THUMB}};
156         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
157         return E_HAS_DB_ERROR;
158     }
159     if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
160         return E_INVALID_FILEID;
161     }
162     string querySql = "SELECT " + MediaColumn::MEDIA_FILE_PATH + " FROM " + table +
163         " WHERE " + MediaColumn::MEDIA_ID + "=?";
164     vector<string> selectionArgs = { fileId };
165     auto resultSet = rdbStorePtr->QuerySql(querySql, selectionArgs);
166     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
167         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
168             {KEY_OPT_TYPE, OptType::THUMB}};
169         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
170         return E_HAS_DB_ERROR;
171     }
172     path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
173     if (path.empty()) {
174         return E_INVALID_PATH;
175     }
176     return E_OK;
177 }
178 #endif
179 
GetThumbFd(const string &path, const string &table, const string &id, const string &uri, const Size &size, bool isAstc)180 int ThumbnailService::GetThumbFd(const string &path, const string &table, const string &id, const string &uri,
181     const Size &size, bool isAstc)
182 {
183     ThumbRdbOpt opts = {
184         .store = rdbStorePtr_,
185         .path = path,
186         .table = table,
187         .row = id,
188         .uri = uri,
189     };
190     ThumbnailType thumbType = GetThumbType(size.width, size.height, isAstc);
191     if (thumbType != ThumbnailType::THUMB && thumbType != ThumbnailType::THUMB_ASTC) {
192         opts.screenSize = screenSize_;
193     }
194     int fd = ThumbnailGenerateHelper::GetThumbnailPixelMap(opts, thumbType);
195     if (fd < 0) {
196         MEDIA_ERR_LOG("GetThumbnailPixelMap failed : %{public}d", fd);
197     }
198     return fd;
199 }
200 
GetKeyFrameThumbFd(const string &path, const string &table, const string &id, const string &uri, int32_t &beginStamp, int32_t &type)201 int ThumbnailService::GetKeyFrameThumbFd(const string &path, const string &table, const string &id, const string &uri,
202     int32_t &beginStamp, int32_t &type)
203 {
204     ThumbRdbOpt opts = {
205         .store = rdbStorePtr_,
206         .path = path,
207         .table = table,
208         .row = id,
209         .uri = uri,
210     };
211 
212     int fd = ThumbnailGenerateHelper::GetKeyFrameThumbnailPixelMap(opts, beginStamp, type);
213     if (fd < 0) {
214         MEDIA_ERR_LOG("GetKeyFrameThumbnailPixelMap failed : %{public}d", fd);
215     }
216     return fd;
217 }
218 
GetThumbnailFd(const string &uri, bool isAstc)219 int ThumbnailService::GetThumbnailFd(const string &uri, bool isAstc)
220 {
221     if (!CheckSizeValid()) {
222         MEDIA_ERR_LOG("GetThumbnailFd failed for invaild size, uri: %{public}s", uri.c_str());
223         return E_THUMBNAIL_INVALID_SIZE;
224     }
225     string id;
226     string path;
227     string table;
228     Size size;
229     if (!ThumbnailUriUtils::ParseThumbnailInfo(uri, id, size, path, table)) {
230         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_FAIL},
231             {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
232         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
233         return E_FAIL;
234     }
235 #ifdef MEDIALIBRARY_COMPATIBILITY
236     if (path.empty()) {
237         int32_t errCode = GetPathFromDb(rdbStorePtr_, id, table, path);
238         if (errCode != E_OK) {
239             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
240                 {KEY_OPT_TYPE, OptType::THUMB}};
241             PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
242             MEDIA_ERR_LOG("GetPathFromDb failed, errCode = %{public}d", errCode);
243             return errCode;
244         }
245     }
246 #endif
247     return GetThumbFd(path, table, id, uri, size, isAstc);
248 }
249 
GetKeyFrameThumbnailFd(const string &uri, bool isAstc)250 int ThumbnailService::GetKeyFrameThumbnailFd(const string &uri, bool isAstc)
251 {
252     if (!CheckSizeValid()) {
253         MEDIA_ERR_LOG("GetKeyFrameThumbnailFd failed for invaild size, uri: %{public}s", uri.c_str());
254         return E_THUMBNAIL_INVALID_SIZE;
255     }
256     string id;
257     string path;
258     int32_t beginStamp;
259     int32_t type;
260     if (!ThumbnailUriUtils::ParseKeyFrameThumbnailInfo(uri, id, beginStamp, type, path)) {
261         MEDIA_ERR_LOG("failed to parse keyFrame thumbnail info");
262         return E_FAIL;
263     }
264     string table = PhotoColumn::HIGHLIGHT_TABLE;
265 #ifdef MEDIALIBRARY_COMPATIBILITY
266     if (path.empty()) {
267         int32_t errCode = GetPathFromDb(rdbStorePtr_, id, table, path);
268         if (errCode != E_OK) {
269             MEDIA_ERR_LOG("GetPathFromDb failed, errCode = %{public}d", errCode);
270             return errCode;
271         }
272     }
273 #endif
274     return GetKeyFrameThumbFd(path, table, id, uri, beginStamp, type);
275 }
276 
ParseThumbnailParam(const std::string &uri, string &fileId, string &networkId, string &tableName)277 int32_t ThumbnailService::ParseThumbnailParam(const std::string &uri, string &fileId, string &networkId,
278     string &tableName)
279 {
280     if (!CheckSizeValid()) {
281         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_INVALID_SIZE},
282             {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
283         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
284         return E_THUMBNAIL_INVALID_SIZE;
285     }
286     if (!ThumbnailUriUtils::ParseFileUri(uri, fileId, networkId, tableName)) {
287         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_ERR},
288             {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
289         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
290         MEDIA_ERR_LOG("ParseThumbnailInfo faild");
291         return E_ERR;
292     }
293     return E_OK;
294 }
295 
CreateThumbnailFileScaned(const std::string &uri, const string &path, bool isSync)296 int32_t ThumbnailService::CreateThumbnailFileScaned(const std::string &uri, const string &path, bool isSync)
297 {
298     string fileId;
299     string networkId;
300     string tableName;
301 
302     int err = ParseThumbnailParam(uri, fileId, networkId, tableName);
303     if (err != E_OK) {
304         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_ERR},
305             {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
306         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
307         return err;
308     }
309 
310     std::string dateTaken = ThumbnailUriUtils::GetDateTakenFromUri(uri);
311     std::string fileUri = ThumbnailUriUtils::GetFileUriFromUri(uri);
312     ThumbRdbOpt opts = {
313         .store = rdbStorePtr_,
314         .path = path,
315         .table = tableName,
316         .row = fileId,
317         .dateTaken = dateTaken,
318         .fileUri = fileUri,
319         .screenSize = screenSize_
320     };
321 
322     err = ThumbnailGenerateHelper::CreateThumbnailFileScaned(opts, isSync);
323     if (err != E_OK) {
324         MEDIA_ERR_LOG("CreateThumbnailFileScaned failed : %{public}d", err);
325         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
326             {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
327         PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
328         return err;
329     }
330     return E_OK;
331 }
332 
InterruptBgworker()333 void ThumbnailService::InterruptBgworker()
334 {
335     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
336     if (asyncWorker != nullptr) {
337         asyncWorker->Interrupt();
338     }
339 
340     std::shared_ptr<ThumbnailGenerateWorker> thumbnailWorker =
341         ThumbnailGenerateWorkerManager::GetInstance().GetThumbnailWorker(ThumbnailTaskType::BACKGROUND);
342     if (thumbnailWorker == nullptr) {
343         MEDIA_ERR_LOG("thumbnailWorker is null");
344         return;
345     }
346     thumbnailWorker->ReleaseTaskQueue(ThumbnailTaskPriority::LOW);
347 }
348 
StopAllWorker()349 void ThumbnailService::StopAllWorker()
350 {
351     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
352     if (asyncWorker != nullptr) {
353         asyncWorker->Stop();
354     }
355 
356     ThumbnailGenerateWorkerManager::GetInstance().ClearAllTask();
357 }
358 
GenerateThumbnailBackground()359 int32_t ThumbnailService::GenerateThumbnailBackground()
360 {
361     if (!CheckSizeValid()) {
362         return E_THUMBNAIL_INVALID_SIZE;
363     }
364     int32_t err = 0;
365     vector<string> tableList;
366     tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
367     tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
368     tableList.emplace_back(MEDIALIBRARY_TABLE);
369 
370     for (const auto &tableName : tableList) {
371         ThumbRdbOpt opts = {
372             .store = rdbStorePtr_,
373 #ifdef DISTRIBUTED
374             .kvStore = kvStorePtr_,
375 #endif
376             .table = tableName
377         };
378 
379         if ((tableName == PhotoColumn::PHOTOS_TABLE) && ThumbnailUtils::IsSupportGenAstc()) {
380             // CreateAstcBackground contains thumbnails created.
381             err = ThumbnailGenerateHelper::CreateAstcBackground(opts);
382             if (err != E_OK) {
383                 MEDIA_ERR_LOG("CreateAstcBackground failed : %{public}d", err);
384             }
385         } else {
386             err = ThumbnailGenerateHelper::CreateThumbnailBackground(opts);
387             if (err != E_OK) {
388                 MEDIA_ERR_LOG("CreateThumbnailBackground failed : %{public}d", err);
389             }
390         }
391 
392         if (tableName == PhotoColumn::PHOTOS_TABLE) {
393             err = ThumbnailGenerateHelper::CreateLcdBackground(opts);
394             if (err != E_OK) {
395                 MEDIA_ERR_LOG("CreateLcdBackground failed : %{public}d", err);
396             }
397         }
398     }
399 
400     return err;
401 }
402 
UpgradeThumbnailBackground(bool isWifiConnected)403 int32_t ThumbnailService::UpgradeThumbnailBackground(bool isWifiConnected)
404 {
405     ThumbRdbOpt opts = {
406         .store = rdbStorePtr_,
407         .table = PhotoColumn::PHOTOS_TABLE
408     };
409     int32_t err = ThumbnailGenerateHelper::UpgradeThumbnailBackground(opts, isWifiConnected);
410     if (err != E_OK) {
411         MEDIA_ERR_LOG("UpgradeThumbnailBackground failed : %{public}d", err);
412     }
413     return err;
414 }
415 
GenerateHighlightThumbnailBackground()416 int32_t ThumbnailService::GenerateHighlightThumbnailBackground()
417 {
418     ThumbRdbOpt opts = {
419         .store = rdbStorePtr_,
420         .table = PhotoColumn::HIGHLIGHT_TABLE
421     };
422     int32_t err = ThumbnailGenerateHelper::GenerateHighlightThumbnailBackground(opts);
423     if (err != E_OK) {
424         MEDIA_ERR_LOG("GenerateHighlightThumbnailBackground failed : %{public}d", err);
425     }
426     return err;
427 }
428 
TriggerHighlightThumbnail(std::string &id, std::string &tracks, std::string &trigger, std::string &genType)429 int32_t ThumbnailService::TriggerHighlightThumbnail(std::string &id, std::string &tracks, std::string &trigger,
430     std::string &genType)
431 {
432     ThumbRdbOpt opts = {
433         .store = rdbStorePtr_,
434         .table = PhotoColumn::HIGHLIGHT_TABLE
435     };
436     int32_t err = ThumbnailGenerateHelper::TriggerHighlightThumbnail(opts, id, tracks, trigger, genType);
437     if (err != E_OK) {
438         MEDIA_ERR_LOG("TriggerHighlightThumbnail failed : %{public}d", err);
439     }
440     return err;
441 }
442 
RestoreThumbnailDualFrame()443 int32_t ThumbnailService::RestoreThumbnailDualFrame()
444 {
445     ThumbRdbOpt opts = {
446         .store = rdbStorePtr_,
447         .table = PhotoColumn::PHOTOS_TABLE
448     };
449     return ThumbnailGenerateHelper::RestoreAstcDualFrame(opts);
450 }
451 
LcdAging()452 int32_t ThumbnailService::LcdAging()
453 {
454     int32_t err = 0;
455     vector<string> tableList;
456     tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
457     tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
458     tableList.emplace_back(MEDIALIBRARY_TABLE);
459 
460     for (const auto &tableName : tableList) {
461         ThumbRdbOpt opts = {
462             .store = rdbStorePtr_,
463 #ifdef DISTRIBUTED
464             .kvStore = kvStorePtr_,
465 #endif
466             .table = tableName,
467         };
468         err = ThumbnailAgingHelper::AgingLcdBatch(opts);
469         if (err != E_OK) {
470             MEDIA_ERR_LOG("AgingLcdBatch failed : %{public}d", err);
471         }
472     }
473 
474     return E_OK;
475 }
476 
477 #ifdef DISTRIBUTED
LcdDistributeAging(const string &udid)478 int32_t ThumbnailService::LcdDistributeAging(const string &udid)
479 {
480     ThumbRdbOpt opts = {
481         .store = rdbStorePtr_,
482         .kvStore = kvStorePtr_,
483         .udid = udid
484     };
485     int32_t err = ThumbnailAgingHelper::AgingDistributeLcdBatch(opts);
486     if (err != E_OK) {
487         MEDIA_ERR_LOG("AgingDistributeLcdBatch failed : %{public}d", err);
488         return err;
489     }
490     return E_OK;
491 }
492 
InvalidateDistributeThumbnail(const string &udid)493 int32_t ThumbnailService::InvalidateDistributeThumbnail(const string &udid)
494 {
495     ThumbRdbOpt opts = {
496         .store = rdbStorePtr_,
497         .kvStore = kvStorePtr_,
498         .udid = udid
499     };
500     int32_t err = ThumbnailAgingHelper::InvalidateDistributeBatch(opts);
501     if (err != E_OK) {
502         MEDIA_ERR_LOG("InvalidateDistributeBatch failed : %{public}d", err);
503     }
504     return err;
505 }
506 #endif
507 
InvalidateThumbnail(const std::string &id, const std::string &tableName, const std::string &path, const std::string &dateTaken)508 void ThumbnailService::InvalidateThumbnail(const std::string &id,
509     const std::string &tableName, const std::string &path, const std::string &dateTaken)
510 {
511     ThumbRdbOpt opts = {
512         .store = rdbStorePtr_,
513         .path = path,
514         .table = tableName,
515         .row = id,
516         .dateTaken = dateTaken,
517     };
518     ThumbnailData thumbnailData;
519     ThumbnailUtils::DeleteOriginImage(opts);
520     if (opts.path.find(ROOT_MEDIA_DIR + PHOTO_BUCKET) != string::npos) {
521         MediaLibraryPhotoOperations::DropThumbnailSize(id);
522     }
523 }
524 
GetAgingDataSize(const int64_t &time, int &count)525 int32_t ThumbnailService::GetAgingDataSize(const int64_t &time, int &count)
526 {
527     int32_t err = 0;
528     vector<string> tableList;
529     tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
530     tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
531     tableList.emplace_back(MEDIALIBRARY_TABLE);
532 
533     for (const auto &tableName : tableList) {
534         ThumbRdbOpt opts = {
535             .store = rdbStorePtr_,
536 #ifdef DISTRIBUTED
537             .kvStore = kvStorePtr_,
538 #endif
539             .table = tableName,
540         };
541         int tempCount = 0;
542         err = ThumbnailAgingHelper::GetAgingDataCount(time, true, opts, tempCount);
543         if (err != E_OK) {
544             MEDIA_ERR_LOG("AgingLcdBatch failed : %{public}d", err);
545             return err;
546         }
547         count += tempCount;
548     }
549 
550     return err;
551 }
552 
QueryNewThumbnailCount(const int64_t &time, int32_t &count)553 int32_t ThumbnailService::QueryNewThumbnailCount(const int64_t &time, int32_t &count)
554 {
555     int32_t err = 0;
556     vector<string> tableList;
557     tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
558     tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
559     tableList.emplace_back(MEDIALIBRARY_TABLE);
560 
561     for (const auto &tableName : tableList) {
562         ThumbRdbOpt opts = {
563             .store = rdbStorePtr_,
564 #ifdef DISTRIBUTED
565             .kvStore = kvStorePtr_,
566 #endif
567             .table = tableName
568         };
569         int32_t tempCount = 0;
570         err = ThumbnailGenerateHelper::GetNewThumbnailCount(opts, time, tempCount);
571         if (err != E_OK) {
572             MEDIA_ERR_LOG("GetNewThumbnailCount failed : %{public}d", err);
573             return err;
574         }
575         count += tempCount;
576     }
577     return E_OK;
578 }
579 
CreateAstcCloudDownload(const string &id, bool isCloudInsertTaskPriorityHigh)580 int32_t ThumbnailService::CreateAstcCloudDownload(const string &id, bool isCloudInsertTaskPriorityHigh)
581 {
582     if (!isCloudInsertTaskPriorityHigh && !currentStatusForTask_) {
583         return E_CLOUD_NOT_SUITABLE_FOR_TASK;
584     }
585     ThumbRdbOpt opts = {
586         .store = rdbStorePtr_,
587         .table = PhotoColumn::PHOTOS_TABLE,
588         .fileId = id,
589     };
590 
591     int err = ThumbnailGenerateHelper::CreateAstcCloudDownload(opts, isCloudInsertTaskPriorityHigh);
592     if (err != E_OK) {
593         MEDIA_ERR_LOG("CreateAstcCloudDownload failed : %{public}d", err);
594         return err;
595     }
596     return err;
597 }
598 
DeleteAstcWithFileIdAndDateTaken(const std::string &fileId, const std::string &dateTaken)599 void ThumbnailService::DeleteAstcWithFileIdAndDateTaken(const std::string &fileId, const std::string &dateTaken)
600 {
601     ThumbnailData data;
602     ThumbRdbOpt opts = {
603         .store = rdbStorePtr_,
604         .table = PhotoColumn::PHOTOS_TABLE,
605         .row = fileId,
606         .dateTaken = dateTaken
607     };
608 
609     IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::DeleteMonthAndYearAstc,
610         opts, data, ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::HIGH);
611 }
612 
CreateAstcBatchOnDemand(NativeRdb::RdbPredicates &rdbPredicate, int32_t requestId)613 int32_t ThumbnailService::CreateAstcBatchOnDemand(NativeRdb::RdbPredicates &rdbPredicate, int32_t requestId)
614 {
615     if (requestId <= 0) {
616         MEDIA_ERR_LOG("create astc batch failed, invalid request id:%{public}d", requestId);
617         return E_INVALID_VALUES;
618     }
619 
620     CancelAstcBatchTask(requestId - 1);
621     ThumbRdbOpt opts = {
622         .store = rdbStorePtr_,
623         .table = PhotoColumn::PHOTOS_TABLE
624     };
625     return ThumbnailGenerateHelper::CreateAstcBatchOnDemand(opts, rdbPredicate, requestId);
626 }
627 
CancelAstcBatchTask(int32_t requestId)628 void ThumbnailService::CancelAstcBatchTask(int32_t requestId)
629 {
630     if (requestId <= 0) {
631         MEDIA_ERR_LOG("cancel astc batch failed, invalid request id:%{public}d", requestId);
632         return;
633     }
634 
635     MEDIA_INFO_LOG("CancelAstcBatchTask requestId: %{public}d", requestId);
636     std::shared_ptr<ThumbnailGenerateWorker> thumbnailWorker =
637         ThumbnailGenerateWorkerManager::GetInstance().GetThumbnailWorker(ThumbnailTaskType::FOREGROUND);
638     if (thumbnailWorker == nullptr) {
639         MEDIA_ERR_LOG("thumbnailWorker is null");
640         return;
641     }
642     thumbnailWorker->IgnoreTaskByRequestId(requestId);
643 }
644 
UpdateAstcWithNewDateTaken(const std::string &fileId, const std::string &newDateTaken, const std::string &formerDateTaken)645 void ThumbnailService::UpdateAstcWithNewDateTaken(const std::string &fileId, const std::string &newDateTaken,
646     const std::string &formerDateTaken)
647 {
648     ThumbnailData data;
649     data.dateTaken = newDateTaken;
650     ThumbRdbOpt opts = {
651         .store = rdbStorePtr_,
652         .table = PhotoColumn::PHOTOS_TABLE,
653         .row = fileId,
654         .dateTaken = formerDateTaken
655     };
656 
657     IThumbnailHelper::AddThumbnailGenerateTask(IThumbnailHelper::UpdateAstcDateTaken,
658         opts, data, ThumbnailTaskType::BACKGROUND, ThumbnailTaskPriority::HIGH);
659 }
660 
CheckCloudThumbnailDownloadFinish()661 int32_t ThumbnailService::CheckCloudThumbnailDownloadFinish()
662 {
663     if (!ThumbnailUtils::CheckCloudThumbnailDownloadFinish(rdbStorePtr_)) {
664         return E_CLOUD_THUMBNAIL_NOT_DOWNLOAD_FINISH;
665     }
666     return E_OK;
667 }
668 
UpdateThumbnailReadyToFailed(ThumbRdbOpt &opts, std::string id)669 static void UpdateThumbnailReadyToFailed(ThumbRdbOpt &opts, std::string id)
670 {
671     if (opts.store == nullptr || id.empty()) {
672         return;
673     }
674 
675     ValuesBucket values;
676     int changedRows;
677     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, THUMBNAIL_READY_FAILED);
678     int32_t err = opts.store->Update(changedRows, opts.table, values, MEDIA_DATA_DB_ID + " = ?", vector<string> { id });
679     if (err != NativeRdb::E_OK) {
680         MEDIA_ERR_LOG("RdbStore Update failed! %{public}d", err);
681     }
682 }
683 
IsAstcChangeOldKeyToNewKeySuccess(std::shared_ptr<MediaLibraryKvStore> &monthKvStore, std::shared_ptr<MediaLibraryKvStore> &yearKvStore, const std::string &oldKey, const std::string &newKey)684 static bool IsAstcChangeOldKeyToNewKeySuccess(std::shared_ptr<MediaLibraryKvStore> &monthKvStore,
685     std::shared_ptr<MediaLibraryKvStore> &yearKvStore, const std::string &oldKey, const std::string &newKey)
686 {
687     if (oldKey.compare(newKey) == 0) {
688         MEDIA_INFO_LOG("OldKey: %{public}s is same to newKey", oldKey.c_str());
689         return true;
690     }
691     std::vector<uint8_t> monthValue;
692     std::vector<uint8_t> yearValue;
693     if (yearKvStore->Query(newKey, yearValue) == E_OK) {
694         MEDIA_INFO_LOG("NewKey Astc exists, fileID %{public}s", newKey.c_str());
695         monthKvStore->Delete(oldKey);
696         yearKvStore->Delete(oldKey);
697         return true;
698     }
699     bool isChangeKeySuccess = true;
700     if (monthKvStore->Query(oldKey, monthValue) != E_OK || monthKvStore->Insert(newKey, monthValue) != E_OK ||
701         monthKvStore->Delete(oldKey) != E_OK) {
702         MEDIA_ERR_LOG("MonthValue update failed, fileID %{public}s", newKey.c_str());
703         isChangeKeySuccess = false;
704     }
705     if (yearKvStore->Query(oldKey, yearValue) != E_OK || yearKvStore->Insert(newKey, yearValue) != E_OK ||
706         yearKvStore->Delete(oldKey) != E_OK) {
707         MEDIA_ERR_LOG("YearValue update failed, fileID %{public}s", newKey.c_str());
708         isChangeKeySuccess = false;
709     }
710     return isChangeKeySuccess;
711 }
712 
AstcChangeKeyFromDateAddedToDateTaken()713 void ThumbnailService::AstcChangeKeyFromDateAddedToDateTaken()
714 {
715     if (rdbStorePtr_ == nullptr) {
716         MEDIA_ERR_LOG("RdbStorePtr is null");
717         return;
718     }
719     vector<ThumbnailData> infos;
720     if (!ThumbnailUtils::QueryOldKeyAstcInfos(rdbStorePtr_, PhotoColumn::PHOTOS_TABLE, infos)) {
721         return;
722     }
723     MEDIA_INFO_LOG("Old key astc data size: %{public}d", static_cast<int>(infos.size()));
724     if (infos.empty()) {
725         return;
726     }
727     ThumbRdbOpt opts = {
728         .store = rdbStorePtr_,
729         .table = PhotoColumn::PHOTOS_TABLE,
730     };
731 
732     auto monthKvStore = MediaLibraryKvStoreManager::GetInstance()
733         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::MONTH_ASTC);
734     if (monthKvStore == nullptr) {
735         MEDIA_ERR_LOG("Init month kvStore failed");
736         return;
737     }
738     auto yearKvStore = MediaLibraryKvStoreManager::GetInstance()
739         .GetKvStore(KvStoreRoleType::OWNER, KvStoreValueType::YEAR_ASTC);
740     if (yearKvStore == nullptr) {
741         MEDIA_ERR_LOG("Init year kvStore failed");
742         return;
743     }
744     for (size_t i = 0; i < infos.size(); i++) {
745         std::string oldKey;
746         std::string newKey;
747         if (!ThumbnailUtils::GenerateKvStoreKey(infos[i].id, infos[i].dateAdded, oldKey) ||
748             !ThumbnailUtils::GenerateKvStoreKey(infos[i].id, infos[i].dateTaken, newKey)) {
749             continue;
750         }
751         if (!IsAstcChangeOldKeyToNewKeySuccess(monthKvStore, yearKvStore, oldKey, newKey)) {
752             monthKvStore->Delete(oldKey);
753             yearKvStore->Delete(oldKey);
754             UpdateThumbnailReadyToFailed(opts, infos[i].id);
755         }
756     }
757     MEDIA_INFO_LOG("PerformKvStoreChangeKeyTask End");
758 }
759 
UpdateCurrentStatusForTask(const bool &currentStatusForTask)760 void ThumbnailService::UpdateCurrentStatusForTask(const bool &currentStatusForTask)
761 {
762     currentStatusForTask_ = currentStatusForTask;
763 }
764 
GetCurrentStatusForTask()765 bool ThumbnailService::GetCurrentStatusForTask()
766 {
767     return currentStatusForTask_;
768 }
769 } // namespace Media
770 } // namespace OHOS
771