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 "ipc_skeleton.h"
20 #include "display_manager.h"
21 #include "media_column.h"
22 #include "medialibrary_async_worker.h"
23 #include "medialibrary_db_const.h"
24 #include "medialibrary_errno.h"
25 #include "medialibrary_kvstore_manager.h"
26 #include "media_log.h"
27 #include "result_set_utils.h"
28 #include "thumbnail_aging_helper.h"
29 #include "thumbnail_const.h"
30 #include "thumbnail_generate_helper.h"
31 #include "thumbnail_helper_factory.h"
32 #include "thumbnail_uri_utils.h"
33 #include "post_event_utils.h"
34
35 using namespace std;
36 using namespace OHOS::DistributedKv;
37 using namespace OHOS::NativeRdb;
38 using namespace OHOS::AbilityRuntime;
39
40 namespace OHOS {
41 namespace Media {
42 std::shared_ptr<ThumbnailService> ThumbnailService::thumbnailServiceInstance_{nullptr};
43 std::mutex ThumbnailService::instanceLock_;
ThumbnailService(void)44 ThumbnailService::ThumbnailService(void)
45 {
46 rdbStorePtr_ = nullptr;
47 #ifdef DISTRIBUTED
48 kvStorePtr_ = nullptr;
49 #endif
50 }
51
GetInstance()52 shared_ptr<ThumbnailService> ThumbnailService::GetInstance()
53 {
54 if (thumbnailServiceInstance_ == nullptr) {
55 std::lock_guard<std::mutex> lockGuard(instanceLock_);
56 if (thumbnailServiceInstance_ != nullptr) {
57 return thumbnailServiceInstance_;
58 }
59 thumbnailServiceInstance_ = shared_ptr<ThumbnailService>(new ThumbnailService());
60 }
61
62 return thumbnailServiceInstance_;
63 }
64
GetDefaultWindowSize(Size & size)65 static bool GetDefaultWindowSize(Size &size)
66 {
67 auto &displayMgr = OHOS::Rosen::DisplayManager::GetInstance();
68 auto display = displayMgr.GetDefaultDisplay();
69 if (display == nullptr) {
70 MEDIA_ERR_LOG("Get display window size failed");
71 return false;
72 }
73 size.width = display->GetWidth();
74 size.height = display->GetHeight();
75 if (size.width <= 0) {
76 MEDIA_WARN_LOG("Get Default display width is invalid %{public}d", size.width);
77 size.width = DEFAULT_LCD_SIZE;
78 }
79 if (size.height <= 0) {
80 MEDIA_WARN_LOG("Get Default display height is invalid %{public}d", size.height);
81 size.height = DEFAULT_LCD_SIZE;
82 }
83 MEDIA_INFO_LOG("display window size::w %{public}d, h %{public}d", size.width, size.height);
84
85 return true;
86 }
87
CheckSizeValid()88 bool ThumbnailService::CheckSizeValid()
89 {
90 if (!isScreenSizeInit_) {
91 if (!GetDefaultWindowSize(screenSize_)) {
92 return false;
93 }
94 isScreenSizeInit_ = true;
95 }
96 return true;
97 }
98
Init(const shared_ptr<RdbStore> & rdbStore,const shared_ptr<SingleKvStore> & kvStore,const shared_ptr<Context> & context)99 void ThumbnailService::Init(const shared_ptr<RdbStore> &rdbStore,
100 #ifdef DISTRIBUTED
101 const shared_ptr<SingleKvStore> &kvStore,
102 #endif
103 const shared_ptr<Context> &context)
104 {
105 rdbStorePtr_ = rdbStore;
106 #ifdef DISTRIBUTED
107 kvStorePtr_ = kvStore;
108 #endif
109 context_ = context;
110
111 if (!GetDefaultWindowSize(screenSize_)) {
112 MEDIA_ERR_LOG("GetDefaultWindowSize failed");
113 } else {
114 isScreenSizeInit_ = true;
115 }
116 }
117
ReleaseService()118 void ThumbnailService::ReleaseService()
119 {
120 StopAllWorker();
121 rdbStorePtr_ = nullptr;
122 #ifdef DISTRIBUTED
123 kvStorePtr_ = nullptr;
124 #endif
125 context_ = nullptr;
126 thumbnailServiceInstance_ = nullptr;
127 }
128
129 #ifdef MEDIALIBRARY_COMPATIBILITY
GetPathFromDb(const shared_ptr<NativeRdb::RdbStore> & rdbStorePtr,const string & fileId,const string & table,string & path)130 static int32_t GetPathFromDb(const shared_ptr<NativeRdb::RdbStore> &rdbStorePtr, const string &fileId,
131 const string &table, string &path)
132 {
133 if (rdbStorePtr == nullptr) {
134 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
135 {KEY_OPT_TYPE, OptType::THUMB}};
136 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
137 return E_HAS_DB_ERROR;
138 }
139 if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
140 return E_INVALID_FILEID;
141 }
142 string querySql = "SELECT " + MediaColumn::MEDIA_FILE_PATH + " FROM " + table +
143 " WHERE " + MediaColumn::MEDIA_ID + "=?";
144 vector<string> selectionArgs = { fileId };
145 auto resultSet = rdbStorePtr->QuerySql(querySql, selectionArgs);
146 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
147 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
148 {KEY_OPT_TYPE, OptType::THUMB}};
149 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
150 return E_HAS_DB_ERROR;
151 }
152 path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
153 if (path.empty()) {
154 return E_INVALID_PATH;
155 }
156 return E_OK;
157 }
158 #endif
159
GetThumbFd(const string & path,const string & table,const string & id,const string & uri,const Size & size,bool isAstc)160 int ThumbnailService::GetThumbFd(const string &path, const string &table, const string &id, const string &uri,
161 const Size &size, bool isAstc)
162 {
163 ThumbRdbOpt opts = {
164 .store = rdbStorePtr_,
165 .path = path,
166 .table = table,
167 .row = id,
168 .uri = uri,
169 };
170 bool isThumbnail = IsThumbnail(size.width, size.height);
171 shared_ptr<IThumbnailHelper> thumbnailHelper =
172 ThumbnailHelperFactory::GetThumbnailHelper(isThumbnail
173 ? ThumbnailHelperType::DEFAULT : ThumbnailHelperType::LCD);
174 if (thumbnailHelper == nullptr) {
175 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_NO_MEMORY},
176 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
177 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
178 return E_NO_MEMORY;
179 }
180 if (!isThumbnail) {
181 opts.screenSize = screenSize_;
182 }
183 int fd = thumbnailHelper->GetThumbnailPixelMap(opts, size, isAstc);
184 if (fd < 0) {
185 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, fd},
186 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
187 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
188 MEDIA_ERR_LOG("GetThumbnailPixelMap failed : %{public}d", fd);
189 }
190 return fd;
191 }
192
GetThumbnailFd(const string & uri,bool isAstc)193 int ThumbnailService::GetThumbnailFd(const string &uri, bool isAstc)
194 {
195 if (!CheckSizeValid()) {
196 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_INVALID_SIZE},
197 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
198 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
199 return E_THUMBNAIL_INVALID_SIZE;
200 }
201 string id;
202 string path;
203 string table;
204 Size size;
205 if (!ThumbnailUriUtils::ParseThumbnailInfo(uri, id, size, path, table)) {
206 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_FAIL},
207 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
208 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
209 return E_FAIL;
210 }
211 #ifdef MEDIALIBRARY_COMPATIBILITY
212 if (path.empty()) {
213 int32_t errCode = GetPathFromDb(rdbStorePtr_, id, table, path);
214 if (errCode != E_OK) {
215 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
216 {KEY_OPT_TYPE, OptType::THUMB}};
217 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
218 MEDIA_ERR_LOG("GetPathFromDb failed, errCode = %{public}d", errCode);
219 return errCode;
220 }
221 }
222 #endif
223 return GetThumbFd(path, table, id, uri, size, isAstc);
224 }
225
ParseThumbnailParam(const std::string & uri,string & fileId,string & networkId,string & tableName)226 int32_t ThumbnailService::ParseThumbnailParam(const std::string &uri, string &fileId, string &networkId,
227 string &tableName)
228 {
229 if (!CheckSizeValid()) {
230 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_THUMBNAIL_INVALID_SIZE},
231 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
232 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
233 return E_THUMBNAIL_INVALID_SIZE;
234 }
235 if (!ThumbnailUriUtils::ParseFileUri(uri, fileId, networkId, tableName)) {
236 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_ERR},
237 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
238 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
239 MEDIA_ERR_LOG("ParseThumbnailInfo faild");
240 return E_ERR;
241 }
242 return E_OK;
243 }
244
CreateThumbnailInfo(const string & path,const string & tableName,const string & fileId,const string & uri,const bool & isSync)245 int32_t ThumbnailService::CreateThumbnailInfo(const string &path, const string &tableName, const string &fileId,
246 const string &uri, const bool &isSync)
247 {
248 int32_t err = CreateDefaultThumbnail(path, tableName, fileId, uri, isSync);
249 if (err != E_OK) {
250 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
251 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
252 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
253 MEDIA_ERR_LOG("CreateDefaultThumbnail failed");
254 return err;
255 }
256
257 err = CreateLcdThumbnail(path, tableName, fileId, isSync);
258 if (err != E_OK) {
259 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
260 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
261 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
262 MEDIA_ERR_LOG("CreateLcdThumbnail failed");
263 return err;
264 }
265 return E_OK;
266 }
267
CreateThumbnail(const std::string & uri,const string & path,bool isSync)268 int32_t ThumbnailService::CreateThumbnail(const std::string &uri, const string &path, bool isSync)
269 {
270 string fileId;
271 string networkId;
272 string tableName;
273
274 int err = ParseThumbnailParam(uri, fileId, networkId, tableName);
275 if (err != E_OK) {
276 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_ERR},
277 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
278 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
279 }
280
281 err = CreateThumbnailInfo(path, tableName, fileId, uri, isSync);
282 if (err != E_OK) {
283 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
284 {KEY_OPT_FILE, uri}, {KEY_OPT_TYPE, OptType::THUMB}};
285 PostEventUtils::GetInstance().PostErrorProcess(ErrType::FILE_OPT_ERR, map);
286 return err;
287 }
288
289 return E_OK;
290 }
291
CreateDefaultThumbnail(const std::string & path,const std::string & tableName,const std::string & fileId,const std::string & uri,const bool & isSync)292 int32_t ThumbnailService::CreateDefaultThumbnail(const std::string &path,
293 const std::string &tableName, const std::string &fileId, const std::string &uri, const bool &isSync)
294 {
295 std::string dateAdded = ThumbnailUriUtils::GetDateAddedFromUri(uri);
296 std::string fileUri = ThumbnailUriUtils::GetFileUriFromUri(uri);
297 shared_ptr<IThumbnailHelper> thumbnailHelper =
298 ThumbnailHelperFactory::GetThumbnailHelper(ThumbnailHelperType::DEFAULT);
299 if (thumbnailHelper == nullptr) {
300 MEDIA_ERR_LOG("thumbnailHelper nullptr");
301 return E_ERR;
302 }
303 ThumbRdbOpt opts = {
304 .store = rdbStorePtr_,
305 .path = path,
306 .table = tableName,
307 .row = fileId,
308 .dateAdded = dateAdded,
309 .fileUri = fileUri,
310 .screenSize = screenSize_
311 };
312 int32_t err = thumbnailHelper->CreateThumbnail(opts, isSync);
313 if (err != E_OK) {
314 MEDIA_ERR_LOG("CreateThumbnail failed : %{public}d", err);
315 return err;
316 }
317 return E_OK;
318 }
319
CreateLcdThumbnail(const std::string & path,const std::string & tableName,const std::string & fileId,const bool & isSync)320 int32_t ThumbnailService::CreateLcdThumbnail(const std::string &path,
321 const std::string &tableName, const std::string &fileId, const bool &isSync)
322 {
323 shared_ptr<IThumbnailHelper> lcdHelper = ThumbnailHelperFactory::GetThumbnailHelper(ThumbnailHelperType::LCD);
324 if (lcdHelper == nullptr) {
325 MEDIA_ERR_LOG("lcdHelper nullptr");
326 return E_ERR;
327 }
328 ThumbRdbOpt opts = {
329 .store = rdbStorePtr_,
330 .path = path,
331 .table = tableName,
332 .row = fileId,
333 .screenSize = screenSize_
334 };
335 int32_t err = lcdHelper->CreateThumbnail(opts, isSync);
336 if (err != E_OK) {
337 MEDIA_ERR_LOG("CreateLcd failed : %{public}d", err);
338 return err;
339 }
340 return E_OK;
341 }
342
InterruptBgworker()343 void ThumbnailService::InterruptBgworker()
344 {
345 shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
346 if (asyncWorker != nullptr) {
347 asyncWorker->Interrupt();
348 }
349 }
350
StopAllWorker()351 void ThumbnailService::StopAllWorker()
352 {
353 shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
354 if (asyncWorker != nullptr) {
355 asyncWorker->Stop();
356 }
357 }
358
GenerateThumbnails()359 int32_t ThumbnailService::GenerateThumbnails()
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 // CreateAstcBatch contains thumbnails created.
381 err = ThumbnailGenerateHelper::CreateAstcBatch(opts);
382 if (err != E_OK) {
383 MEDIA_ERR_LOG("CreateAstcBatch failed : %{public}d", err);
384 }
385 } else {
386 err = ThumbnailGenerateHelper::CreateThumbnailBatch(opts);
387 if (err != E_OK) {
388 MEDIA_ERR_LOG("CreateThumbnailBatch failed : %{public}d", err);
389 }
390 }
391
392 if (tableName != AudioColumn::AUDIOS_TABLE) {
393 err = ThumbnailGenerateHelper::CreateLcdBatch(opts);
394 if (err != E_OK) {
395 MEDIA_ERR_LOG("CreateLcdBatch failed : %{public}d", err);
396 }
397 }
398 }
399
400 return err;
401 }
402
LcdAging()403 int32_t ThumbnailService::LcdAging()
404 {
405 int32_t err = 0;
406 vector<string> tableList;
407 tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
408 tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
409 tableList.emplace_back(MEDIALIBRARY_TABLE);
410
411 for (const auto &tableName : tableList) {
412 ThumbRdbOpt opts = {
413 .store = rdbStorePtr_,
414 #ifdef DISTRIBUTED
415 .kvStore = kvStorePtr_,
416 #endif
417 .table = tableName,
418 };
419 err = ThumbnailAgingHelper::AgingLcdBatch(opts);
420 if (err != E_OK) {
421 MEDIA_ERR_LOG("AgingLcdBatch failed : %{public}d", err);
422 }
423 }
424
425 return E_OK;
426 }
427
428 #ifdef DISTRIBUTED
LcdDistributeAging(const string & udid)429 int32_t ThumbnailService::LcdDistributeAging(const string &udid)
430 {
431 ThumbRdbOpt opts = {
432 .store = rdbStorePtr_,
433 .kvStore = kvStorePtr_,
434 .udid = udid
435 };
436 int32_t err = ThumbnailAgingHelper::AgingDistributeLcdBatch(opts);
437 if (err != E_OK) {
438 MEDIA_ERR_LOG("AgingDistributeLcdBatch failed : %{public}d", err);
439 return err;
440 }
441 return E_OK;
442 }
443
InvalidateDistributeThumbnail(const string & udid)444 int32_t ThumbnailService::InvalidateDistributeThumbnail(const string &udid)
445 {
446 ThumbRdbOpt opts = {
447 .store = rdbStorePtr_,
448 .kvStore = kvStorePtr_,
449 .udid = udid
450 };
451 int32_t err = ThumbnailAgingHelper::InvalidateDistributeBatch(opts);
452 if (err != E_OK) {
453 MEDIA_ERR_LOG("InvalidateDistributeBatch failed : %{public}d", err);
454 }
455 return err;
456 }
457 #endif
458
InvalidateThumbnail(const std::string & id,const std::string & tableName,const std::string & path)459 void ThumbnailService::InvalidateThumbnail(const std::string &id, const std::string &tableName, const std::string &path)
460 {
461 ThumbRdbOpt opts = {
462 .store = rdbStorePtr_,
463 .path = path,
464 .table = tableName,
465 .row = id,
466 };
467 ThumbnailData thumbnailData;
468 ThumbnailUtils::DeleteOriginImage(opts);
469 }
470
GetAgingDataSize(const int64_t & time,int & count)471 int32_t ThumbnailService::GetAgingDataSize(const int64_t &time, int &count)
472 {
473 int32_t err = 0;
474 vector<string> tableList;
475 tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
476 tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
477 tableList.emplace_back(MEDIALIBRARY_TABLE);
478
479 for (const auto &tableName : tableList) {
480 ThumbRdbOpt opts = {
481 .store = rdbStorePtr_,
482 #ifdef DISTRIBUTED
483 .kvStore = kvStorePtr_,
484 #endif
485 .table = tableName,
486 };
487 int tempCount = 0;
488 err = ThumbnailAgingHelper::GetAgingDataCount(time, true, opts, tempCount);
489 if (err != E_OK) {
490 MEDIA_ERR_LOG("AgingLcdBatch failed : %{public}d", err);
491 return err;
492 }
493 count += tempCount;
494 }
495
496 return err;
497 }
498
QueryNewThumbnailCount(const int64_t & time,int32_t & count)499 int32_t ThumbnailService::QueryNewThumbnailCount(const int64_t &time, int32_t &count)
500 {
501 int32_t err = 0;
502 vector<string> tableList;
503 tableList.emplace_back(PhotoColumn::PHOTOS_TABLE);
504 tableList.emplace_back(AudioColumn::AUDIOS_TABLE);
505 tableList.emplace_back(MEDIALIBRARY_TABLE);
506
507 for (const auto &tableName : tableList) {
508 ThumbRdbOpt opts = {
509 .store = rdbStorePtr_,
510 #ifdef DISTRIBUTED
511 .kvStore = kvStorePtr_,
512 #endif
513 .table = tableName
514 };
515 int32_t tempCount = 0;
516 err = ThumbnailGenerateHelper::GetNewThumbnailCount(opts, time, tempCount);
517 if (err != E_OK) {
518 MEDIA_ERR_LOG("CreateThumbnailBatch failed : %{public}d", err);
519 return err;
520 }
521 count += tempCount;
522 }
523 return E_OK;
524 }
525
CreateAstcFromFileId(const string & id)526 int32_t ThumbnailService::CreateAstcFromFileId(const string &id)
527 {
528 ThumbnailData data;
529 int err = 0;
530 ThumbRdbOpt opts = {
531 .store = rdbStorePtr_,
532 #ifdef DISTRIBUTED
533 .kvStore = kvStorePtr_,
534 #endif
535 .table = PhotoColumn::PHOTOS_TABLE
536 };
537
538 ThumbnailUtils::QueryThumbnailDataFromFileId(opts, id, data, err);
539 if (err != E_OK) {
540 return err;
541 }
542
543 IThumbnailHelper::AddAsyncTask(IThumbnailHelper::CreateAstc, opts, data, true);
544 return E_OK;
545 }
546
547 } // namespace Media
548 } // namespace OHOS
549