1 /*
2 * Copyright (C) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define MLOG_TAG "DataManager"
17
18 #include "medialibrary_data_manager.h"
19
20 #include <shared_mutex>
21 #include <unordered_set>
22
23 #include "ability_scheduler_interface.h"
24 #include "abs_rdb_predicates.h"
25 #include "acl.h"
26 #include "background_task_mgr_helper.h"
27 #include "cloud_sync_helper.h"
28 #include "datashare_abs_result_set.h"
29 #ifdef DISTRIBUTED
30 #include "device_manager.h"
31 #include "device_manager_callback.h"
32 #endif
33 #include "efficiency_resource_info.h"
34 #include "hitrace_meter.h"
35 #include "ipc_skeleton.h"
36 #include "media_column.h"
37 #include "media_datashare_ext_ability.h"
38 #include "media_file_utils.h"
39 #include "media_log.h"
40 #include "media_scanner_manager.h"
41 #include "medialibrary_album_operations.h"
42 #include "medialibrary_asset_operations.h"
43 #include "medialibrary_async_worker.h"
44 #include "medialibrary_audio_operations.h"
45 #include "medialibrary_bundle_manager.h"
46 #include "medialibrary_common_utils.h"
47 #ifdef DISTRIBUTED
48 #include "medialibrary_device.h"
49 #include "medialibrary_device_info.h"
50 #endif
51 #include "medialibrary_dir_operations.h"
52 #include "medialibrary_errno.h"
53 #include "medialibrary_file_operations.h"
54 #include "medialibrary_inotify.h"
55 #include "medialibrary_kvstore_manager.h"
56 #include "medialibrary_location_operations.h"
57 #include "medialibrary_object_utils.h"
58 #include "medialibrary_rdb_utils.h"
59 #include "medialibrary_rdbstore.h"
60 #include "medialibrary_smartalbum_map_operations.h"
61 #include "medialibrary_smartalbum_operations.h"
62 #include "medialibrary_sync_operation.h"
63 #include "medialibrary_tracer.h"
64 #include "medialibrary_unistore_manager.h"
65 #include "medialibrary_uripermission_operations.h"
66 #include "medialibrary_vision_operations.h"
67 #include "medialibrary_search_operations.h"
68 #include "mimetype_utils.h"
69 #include "multistages_capture_manager.h"
70 #include "permission_utils.h"
71 #include "photo_map_operations.h"
72 #include "resource_type.h"
73 #include "rdb_store.h"
74 #include "rdb_utils.h"
75 #include "result_set_utils.h"
76 #include "system_ability_definition.h"
77 #include "timer.h"
78 #include "trash_async_worker.h"
79 #include "value_object.h"
80 #include "post_event_utils.h"
81 #include "medialibrary_formmap_operations.h"
82 #include "ithumbnail_helper.h"
83
84 using namespace std;
85 using namespace OHOS::AppExecFwk;
86 using namespace OHOS::AbilityRuntime;
87 using namespace OHOS::NativeRdb;
88 using namespace OHOS::DistributedKv;
89 using namespace OHOS::DataShare;
90 using namespace OHOS::RdbDataShareAdapter;
91
92 namespace {
93 const OHOS::DistributedKv::AppId KVSTORE_APPID = {"com.ohos.medialibrary.medialibrarydata"};
94 const OHOS::DistributedKv::StoreId KVSTORE_STOREID = {"medialibrary_thumbnail"};
95 };
96
97 namespace OHOS {
98 namespace Media {
99 shared_ptr<MediaLibraryDataManager> MediaLibraryDataManager::instance_ = nullptr;
100 unordered_map<string, DirAsset> MediaLibraryDataManager::dirQuerySetMap_ = {};
101 mutex MediaLibraryDataManager::mutex_;
102 Utils::Timer MediaLibraryDataManager::timer_("download_cloud_files");
103 uint32_t MediaLibraryDataManager::timerId_ = 0;
104
105 static constexpr int32_t LOCAL_FILES_COUNT_THRESHOLD = 10000;
106 static constexpr int32_t DOWNLOAD_BATCH_SIZE = 5;
107 static constexpr int32_t BATCH_DOWNLOAD_INTERVAL = 60 * 1000; // 1min
108
109 #ifdef DISTRIBUTED
110 static constexpr int MAX_QUERY_THUMBNAIL_KEY_COUNT = 20;
111 #endif
MediaLibraryDataManager(void)112 MediaLibraryDataManager::MediaLibraryDataManager(void)
113 {
114 }
115
~MediaLibraryDataManager(void)116 MediaLibraryDataManager::~MediaLibraryDataManager(void)
117 {
118 MediaLibraryKvStoreManager::GetInstance().CloseAllKvStore();
119 #ifdef DISTRIBUTED
120 if (kvStorePtr_ != nullptr) {
121 dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
122 kvStorePtr_ = nullptr;
123 }
124 #endif
125 }
126
GetInstance()127 shared_ptr<MediaLibraryDataManager> MediaLibraryDataManager::GetInstance()
128 {
129 if (instance_ == nullptr) {
130 lock_guard<mutex> lock(mutex_);
131 if (instance_ == nullptr) {
132 instance_ = make_shared<MediaLibraryDataManager>();
133 }
134 }
135 return instance_;
136 }
137
MediaDataShareCreator(const unique_ptr<Runtime> & runtime)138 static DataShare::DataShareExtAbility *MediaDataShareCreator(const unique_ptr<Runtime> &runtime)
139 {
140 MEDIA_DEBUG_LOG("MediaLibraryCreator::%{public}s", __func__);
141 return MediaDataShareExtAbility::Create(runtime);
142 }
143
RegisterDataShareCreator()144 __attribute__((constructor)) void RegisterDataShareCreator()
145 {
146 MEDIA_DEBUG_LOG("MediaLibraryDataManager::%{public}s", __func__);
147 DataShare::DataShareExtAbility::SetCreator(MediaDataShareCreator);
148 MEDIA_DEBUG_LOG("MediaLibraryDataManager::%{public}s End", __func__);
149 }
150
MakeRootDirs(AsyncTaskData * data)151 static void MakeRootDirs(AsyncTaskData *data)
152 {
153 for (auto &dir : PRESET_ROOT_DIRS) {
154 Uri createAlbumUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_ALBUMOPRN + "/" + MEDIA_ALBUMOPRN_CREATEALBUM);
155 ValuesBucket valuesBucket;
156 valuesBucket.PutString(MEDIA_DATA_DB_FILE_PATH, ROOT_MEDIA_DIR + dir);
157 MediaLibraryCommand cmd(createAlbumUri, valuesBucket);
158 auto ret = MediaLibraryAlbumOperations::CreateAlbumOperation(cmd);
159 if (ret == E_FILE_EXIST) {
160 MEDIA_INFO_LOG("Root dir: %{private}s is exist", dir.c_str());
161 } else if (ret <= 0) {
162 MEDIA_ERR_LOG("Failed to preset root dir: %{private}s", dir.c_str());
163 }
164 MediaFileUtils::CreateDirectory(ROOT_MEDIA_DIR + dir + ".recycle");
165 }
166 }
167
InitMediaLibraryMgr(const shared_ptr<OHOS::AbilityRuntime::Context> & context,const shared_ptr<OHOS::AbilityRuntime::Context> & extensionContext)168 int32_t MediaLibraryDataManager::InitMediaLibraryMgr(const shared_ptr<OHOS::AbilityRuntime::Context> &context,
169 const shared_ptr<OHOS::AbilityRuntime::Context> &extensionContext)
170 {
171 lock_guard<shared_mutex> lock(mgrSharedMutex_);
172
173 if (refCnt_.load() > 0) {
174 MEDIA_DEBUG_LOG("already initialized");
175 refCnt_++;
176 return E_OK;
177 }
178
179 BackgroundTaskMgr::EfficiencyResourceInfo resourceInfo =
180 BackgroundTaskMgr::EfficiencyResourceInfo(BackgroundTaskMgr::ResourceType::CPU, true, 0, "apply", true, true);
181 BackgroundTaskMgr::BackgroundTaskMgrHelper::ApplyEfficiencyResources(resourceInfo);
182
183 context_ = context;
184 int32_t errCode = InitMediaLibraryRdbStore();
185 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "failed at InitMediaLibraryRdbStore");
186
187 #ifdef DISTRIBUTED
188 errCode = InitDeviceData();
189 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "failed at InitDeviceData");
190 #endif
191
192 MimeTypeUtils::InitMimeTypeMap();
193 errCode = MakeDirQuerySetMap(dirQuerySetMap_);
194 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "failed at MakeDirQuerySetMap");
195
196 InitACLPermission();
197
198 shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
199 if (asyncWorker == nullptr) {
200 MEDIA_ERR_LOG("Can not get asyncWorker");
201 return E_ERR;
202 }
203 shared_ptr<MediaLibraryAsyncTask> makeRootDirTask = make_shared<MediaLibraryAsyncTask>(MakeRootDirs, nullptr);
204 if (makeRootDirTask != nullptr) {
205 asyncWorker->AddTask(makeRootDirTask, true);
206 } else {
207 MEDIA_WARN_LOG("Can not init make root dir task");
208 }
209
210 errCode = InitialiseThumbnailService(extensionContext);
211 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "failed at InitialiseThumbnailService");
212
213 InitRefreshAlbum();
214
215 cloudDataObserver_ = std::make_shared<CloudThumbnailObserver>();
216 auto shareHelper = MediaLibraryHelperContainer::GetInstance()->GetDataShareHelper();
217 shareHelper->RegisterObserverExt(Uri(PHOTO_URI_PREFIX), cloudDataObserver_, true);
218
219 refCnt_++;
220 return E_OK;
221 }
222
223 #ifdef DISTRIBUTED
InitDeviceData()224 int32_t MediaLibraryDataManager::InitDeviceData()
225 {
226 if (rdbStore_ == nullptr) {
227 MEDIA_ERR_LOG("MediaLibraryDataManager InitDeviceData rdbStore is null");
228 return E_ERR;
229 }
230
231 MediaLibraryTracer tracer;
232 tracer.Start("InitDeviceRdbStoreTrace");
233 if (!MediaLibraryDevice::GetInstance()->InitDeviceRdbStore(rdbStore_)) {
234 MEDIA_ERR_LOG("MediaLibraryDataManager InitDeviceData failed!");
235 return E_ERR;
236 }
237 return E_OK;
238 }
239 #endif
240
ClearMediaLibraryMgr()241 void MediaLibraryDataManager::ClearMediaLibraryMgr()
242 {
243 lock_guard<shared_mutex> lock(mgrSharedMutex_);
244
245 refCnt_--;
246 if (refCnt_.load() > 0) {
247 MEDIA_DEBUG_LOG("still other extension exist");
248 return;
249 }
250
251 UnregisterTimer();
252 auto shareHelper = MediaLibraryHelperContainer::GetInstance()->GetDataShareHelper();
253 shareHelper->UnregisterObserverExt(Uri(PHOTO_URI_PREFIX), cloudDataObserver_);
254 rdbStore_ = nullptr;
255 MediaLibraryKvStoreManager::GetInstance().CloseAllKvStore();
256
257 #ifdef DISTRIBUTED
258 if (kvStorePtr_ != nullptr) {
259 dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
260 kvStorePtr_ = nullptr;
261 }
262
263 if (MediaLibraryDevice::GetInstance()) {
264 MediaLibraryDevice::GetInstance()->Stop();
265 };
266 #endif
267
268 if (thumbnailService_ != nullptr) {
269 thumbnailService_->ReleaseService();
270 thumbnailService_ = nullptr;
271 }
272 auto watch = MediaLibraryInotify::GetInstance();
273 if (watch != nullptr) {
274 watch->DoStop();
275 }
276 MediaLibraryUnistoreManager::GetInstance().Stop();
277 extension_ = nullptr;
278 }
279
InitMediaLibraryRdbStore()280 int32_t MediaLibraryDataManager::InitMediaLibraryRdbStore()
281 {
282 if (rdbStore_) {
283 return E_OK;
284 }
285
286 int32_t ret = MediaLibraryUnistoreManager::GetInstance().Init(context_);
287 if (ret != E_OK) {
288 MEDIA_ERR_LOG("init MediaLibraryUnistoreManager failed");
289 return ret;
290 }
291 rdbStore_ = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw()->GetRaw();
292 if (ret != E_OK) {
293 MEDIA_ERR_LOG("rdbStore is nullptr");
294 return E_ERR;
295 }
296
297 return E_OK;
298 }
299
InitRefreshAlbum()300 void MediaLibraryDataManager::InitRefreshAlbum()
301 {
302 bool isNeedRefresh = false;
303 int32_t ret = MediaLibraryRdbUtils::IsNeedRefreshByCheckTable(rdbStore_, isNeedRefresh);
304 if (ret != E_OK || isNeedRefresh) {
305 // Only set flag here, should not do any task in InitDataMgr
306 MediaLibraryRdbUtils::SetNeedRefreshAlbum(true);
307 }
308 }
309
GetOwner()310 shared_ptr<MediaDataShareExtAbility> MediaLibraryDataManager::GetOwner()
311 {
312 return extension_;
313 }
314
SetOwner(const shared_ptr<MediaDataShareExtAbility> & datashareExternsion)315 void MediaLibraryDataManager::SetOwner(const shared_ptr<MediaDataShareExtAbility> &datashareExternsion)
316 {
317 extension_ = datashareExternsion;
318 }
319
GetType(const Uri & uri)320 string MediaLibraryDataManager::GetType(const Uri &uri)
321 {
322 MEDIA_INFO_LOG("GetType uri: %{private}s", uri.ToString().c_str());
323 return "";
324 }
325
MakeDirQuerySetMap(unordered_map<string,DirAsset> & outDirQuerySetMap)326 int32_t MediaLibraryDataManager::MakeDirQuerySetMap(unordered_map<string, DirAsset> &outDirQuerySetMap)
327 {
328 int32_t count = -1;
329 vector<string> columns;
330 AbsRdbPredicates dirAbsPred(MEDIATYPE_DIRECTORY_TABLE);
331 auto queryResultSet = rdbStore_->QueryByStep(dirAbsPred, columns);
332 auto ret = queryResultSet->GetRowCount(count);
333 if (ret != NativeRdb::E_OK) {
334 MEDIA_ERR_LOG("rdb failed");
335 return E_ERR;
336 }
337 MEDIA_INFO_LOG("MakeDirQuerySetMap count = %{public}d", count);
338 if (count == 0) {
339 MEDIA_ERR_LOG("can not find any dirAsset");
340 return E_ERR;
341 }
342 DirAsset dirAsset;
343 string dirVal;
344 outDirQuerySetMap.clear();
345 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
346 dirVal = get<string>(
347 ResultSetUtils::GetValFromColumn(DIRECTORY_DB_DIRECTORY, queryResultSet, TYPE_STRING));
348 dirAsset.SetDirectory(dirVal);
349 dirAsset.SetDirType(get<int32_t>(
350 ResultSetUtils::GetValFromColumn(DIRECTORY_DB_DIRECTORY_TYPE, queryResultSet, TYPE_INT32)));
351 dirAsset.SetMediaTypes(get<string>(
352 ResultSetUtils::GetValFromColumn(DIRECTORY_DB_MEDIA_TYPE, queryResultSet, TYPE_STRING)));
353 dirAsset.SetExtensions(get<string>(
354 ResultSetUtils::GetValFromColumn(DIRECTORY_DB_EXTENSION, queryResultSet, TYPE_STRING)));
355 outDirQuerySetMap.insert(make_pair(dirVal, dirAsset));
356 }
357 return E_OK;
358 }
359
GetDirQuerySetMap()360 unordered_map<string, DirAsset> MediaLibraryDataManager::GetDirQuerySetMap()
361 {
362 return dirQuerySetMap_;
363 }
364
365 #ifdef MEDIALIBRARY_COMPATIBILITY
ChangeUriFromValuesBucket(ValuesBucket & values)366 static void ChangeUriFromValuesBucket(ValuesBucket &values)
367 {
368 if (!values.HasColumn(MEDIA_DATA_DB_URI)) {
369 return;
370 }
371
372 ValueObject value;
373 if (!values.GetObject(MEDIA_DATA_DB_URI, value)) {
374 return;
375 }
376 string oldUri;
377 if (value.GetString(oldUri) != NativeRdb::E_OK) {
378 return;
379 }
380 string newUri = MediaFileUtils::GetRealUriFromVirtualUri(oldUri);
381 values.Delete(MEDIA_DATA_DB_URI);
382 values.PutString(MEDIA_DATA_DB_URI, newUri);
383 }
384 #endif
385
SolveInsertCmd(MediaLibraryCommand & cmd)386 int32_t MediaLibraryDataManager::SolveInsertCmd(MediaLibraryCommand &cmd)
387 {
388 switch (cmd.GetOprnObject()) {
389 case OperationObject::FILESYSTEM_ASSET:
390 return MediaLibraryFileOperations::HandleFileOperation(cmd);
391
392 case OperationObject::FILESYSTEM_PHOTO:
393 case OperationObject::FILESYSTEM_AUDIO:
394 return MediaLibraryAssetOperations::HandleInsertOperation(cmd);
395
396 case OperationObject::FILESYSTEM_ALBUM:
397 return MediaLibraryAlbumOperations::CreateAlbumOperation(cmd);
398
399 case OperationObject::ANALYSIS_PHOTO_ALBUM:
400 case OperationObject::PHOTO_ALBUM:
401 return MediaLibraryAlbumOperations::HandlePhotoAlbumOperations(cmd);
402
403 case OperationObject::FILESYSTEM_DIR:
404 return MediaLibraryDirOperations::HandleDirOperation(cmd);
405
406 case OperationObject::SMART_ALBUM:
407 return MediaLibrarySmartAlbumOperations::HandleSmartAlbumOperation(cmd);
408
409 case OperationObject::SMART_ALBUM_MAP:
410 return MediaLibrarySmartAlbumMapOperations::HandleSmartAlbumMapOperation(cmd);
411
412 case OperationObject::THUMBNAIL:
413 return HandleThumbnailOperations(cmd);
414
415 case OperationObject::BUNDLE_PERMISSION:
416 return UriPermissionOperations::HandleUriPermOperations(cmd);
417
418 case OperationObject::VISION_START ... OperationObject::VISION_END:
419 return MediaLibraryVisionOperations::InsertOperation(cmd);
420
421 case OperationObject::GEO_DICTIONARY:
422 case OperationObject::GEO_KNOWLEDGE:
423 case OperationObject::GEO_PHOTO:
424 return MediaLibraryLocationOperations::InsertOperation(cmd);
425
426 case OperationObject::PAH_FORM_MAP:
427 return MediaLibraryFormMapOperations::HandleStoreFormIdOperation(cmd);
428 case OperationObject::SEARCH_TOTAL: {
429 return MediaLibrarySearchOperations::InsertOperation(cmd);
430 }
431
432 case OperationObject::ANALYSIS_PHOTO_MAP: {
433 return MediaLibrarySearchOperations::InsertOperation(cmd);
434 }
435
436 default:
437 MEDIA_ERR_LOG("MediaLibraryDataManager SolveInsertCmd: unsupported OperationObject: %{public}d",
438 cmd.GetOprnObject());
439 return E_FAIL;
440 }
441 }
442
Insert(MediaLibraryCommand & cmd,const DataShareValuesBucket & dataShareValue)443 int32_t MediaLibraryDataManager::Insert(MediaLibraryCommand &cmd, const DataShareValuesBucket &dataShareValue)
444 {
445 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
446 if (refCnt_.load() <= 0) {
447 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
448 return E_FAIL;
449 }
450
451 ValuesBucket value = RdbUtils::ToValuesBucket(dataShareValue);
452 if (value.IsEmpty()) {
453 MEDIA_ERR_LOG("MediaLibraryDataManager Insert: Input parameter is invalid");
454 return E_INVALID_VALUES;
455 }
456 #ifdef MEDIALIBRARY_COMPATIBILITY
457 ChangeUriFromValuesBucket(value);
458 #endif
459 cmd.SetValueBucket(value);
460
461 OperationType oprnType = cmd.GetOprnType();
462 if (oprnType == OperationType::CREATE || oprnType == OperationType::SUBMIT_CACHE) {
463 if (SetCmdBundleAndDevice(cmd) != ERR_OK) {
464 MEDIA_ERR_LOG("MediaLibraryDataManager SetCmdBundleAndDevice failed.");
465 }
466 }
467 // boardcast operation
468 if (oprnType == OperationType::SCAN) {
469 return MediaScannerManager::GetInstance()->ScanDir(ROOT_MEDIA_DIR, nullptr);
470 #ifdef MEDIALIBRARY_MEDIATOOL_ENABLE
471 } else if (oprnType == OperationType::DELETE_TOOL) {
472 return MediaLibraryAssetOperations::DeleteToolOperation(cmd);
473 #endif
474 }
475 return SolveInsertCmd(cmd);
476 }
477
InsertExt(MediaLibraryCommand & cmd,const DataShareValuesBucket & dataShareValue,string & result)478 int32_t MediaLibraryDataManager::InsertExt(MediaLibraryCommand &cmd, const DataShareValuesBucket &dataShareValue,
479 string &result)
480 {
481 int32_t res = Insert(cmd, dataShareValue);
482 result = cmd.GetResult();
483 return res;
484 }
485
HandleThumbnailOperations(MediaLibraryCommand & cmd)486 int32_t MediaLibraryDataManager::HandleThumbnailOperations(MediaLibraryCommand &cmd)
487 {
488 if (thumbnailService_ == nullptr) {
489 return E_THUMBNAIL_SERVICE_NULLPTR;
490 }
491 int32_t result = E_FAIL;
492 switch (cmd.GetOprnType()) {
493 case OperationType::GENERATE:
494 result = thumbnailService_->GenerateThumbnails();
495 break;
496 case OperationType::AGING:
497 result = thumbnailService_->LcdAging();
498 break;
499 #ifdef DISTRIBUTED
500 case OperationType::DISTRIBUTE_AGING:
501 result = DistributeDeviceAging();
502 break;
503 #endif
504 default:
505 MEDIA_ERR_LOG("bad operation type %{public}u", cmd.GetOprnType());
506 }
507 return result;
508 }
509
BatchInsert(MediaLibraryCommand & cmd,const vector<DataShareValuesBucket> & values)510 int32_t MediaLibraryDataManager::BatchInsert(MediaLibraryCommand &cmd, const vector<DataShareValuesBucket> &values)
511 {
512 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
513 if (refCnt_.load() <= 0) {
514 MEDIA_ERR_LOG("MediaLibraryDataManager is not initialized");
515 return E_FAIL;
516 }
517
518 string uriString = cmd.GetUri().ToString();
519 if (uriString == UFM_PHOTO_ALBUM_ADD_ASSET || uriString == PAH_PHOTO_ALBUM_ADD_ASSET) {
520 return PhotoMapOperations::AddPhotoAssets(values);
521 } else if (cmd.GetOprnObject() == OperationObject::ANALYSIS_PHOTO_MAP) {
522 return PhotoMapOperations::AddAnaLysisPhotoAssets(values);
523 }
524 if (uriString.find(MEDIALIBRARY_DATA_URI) == string::npos) {
525 MEDIA_ERR_LOG("MediaLibraryDataManager BatchInsert: Input parameter is invalid");
526 return E_INVALID_URI;
527 }
528 int32_t rowCount = 0;
529 for (auto it = values.begin(); it != values.end(); it++) {
530 if (Insert(cmd, *it) >= 0) {
531 rowCount++;
532 }
533 }
534
535 return rowCount;
536 }
537
Delete(MediaLibraryCommand & cmd,const DataSharePredicates & predicates)538 int32_t MediaLibraryDataManager::Delete(MediaLibraryCommand &cmd, const DataSharePredicates &predicates)
539 {
540 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
541 if (refCnt_.load() <= 0) {
542 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
543 return E_FAIL;
544 }
545
546 string uriString = cmd.GetUri().ToString();
547 if (MediaFileUtils::StartsWith(uriString, PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
548 return MediaLibraryAssetOperations::DeleteOperation(cmd);
549 }
550
551 if (uriString.find(MEDIALIBRARY_DATA_URI) == string::npos) {
552 MEDIA_ERR_LOG("Not Data ability Uri");
553 return E_INVALID_URI;
554 }
555 MediaLibraryTracer tracer;
556 tracer.Start("CheckWhereClause");
557 auto whereClause = predicates.GetWhereClause();
558 if (!MediaLibraryCommonUtils::CheckWhereClause(whereClause)) {
559 MEDIA_ERR_LOG("illegal query whereClause input %{private}s", whereClause.c_str());
560 return E_SQL_CHECK_FAIL;
561 }
562 tracer.Finish();
563
564 // MEDIALIBRARY_TABLE just for RdbPredicates
565 NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(predicates,
566 cmd.GetTableName());
567 cmd.GetAbsRdbPredicates()->SetWhereClause(rdbPredicate.GetWhereClause());
568 cmd.GetAbsRdbPredicates()->SetWhereArgs(rdbPredicate.GetWhereArgs());
569 return DeleteInRdbPredicates(cmd, rdbPredicate);
570 }
571
CheckIsDismissAsset(NativeRdb::RdbPredicates & rdbPredicate)572 bool CheckIsDismissAsset(NativeRdb::RdbPredicates &rdbPredicate)
573 {
574 auto whereClause = rdbPredicate.GetWhereClause();
575 if (whereClause.find(MAP_ALBUM) != string::npos && whereClause.find(MAP_ASSET) != string::npos) {
576 return true;
577 }
578 return false;
579 }
580
DeleteInRdbPredicates(MediaLibraryCommand & cmd,NativeRdb::RdbPredicates & rdbPredicate)581 int32_t MediaLibraryDataManager::DeleteInRdbPredicates(MediaLibraryCommand &cmd, NativeRdb::RdbPredicates &rdbPredicate)
582 {
583 switch (cmd.GetOprnObject()) {
584 case OperationObject::FILESYSTEM_ASSET:
585 case OperationObject::FILESYSTEM_DIR:
586 case OperationObject::FILESYSTEM_ALBUM: {
587 vector<string> columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_PARENT_ID,
588 MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_IS_TRASH, MEDIA_DATA_DB_RELATIVE_PATH };
589 auto fileAsset = MediaLibraryObjectUtils::GetFileAssetByPredicates(*cmd.GetAbsRdbPredicates(), columns);
590 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_ARGUMENTS, "Get fileAsset failed.");
591 if (fileAsset->GetRelativePath() == "") {
592 return E_DELETE_DENIED;
593 }
594 return (fileAsset->GetMediaType() != MEDIA_TYPE_ALBUM) ?
595 MediaLibraryObjectUtils::DeleteFileObj(move(fileAsset)) :
596 MediaLibraryObjectUtils::DeleteDirObj(move(fileAsset));
597 }
598 case OperationObject::PHOTO_ALBUM: {
599 return MediaLibraryAlbumOperations::DeletePhotoAlbum(rdbPredicate);
600 }
601 case OperationObject::PHOTO_MAP: {
602 return PhotoMapOperations::RemovePhotoAssets(rdbPredicate);
603 }
604 case OperationObject::ANALYSIS_PHOTO_MAP: {
605 if (CheckIsDismissAsset(rdbPredicate)) {
606 return PhotoMapOperations::DismissAssets(rdbPredicate);
607 }
608 break;
609 }
610 case OperationObject::FILESYSTEM_PHOTO:
611 case OperationObject::FILESYSTEM_AUDIO: {
612 return MediaLibraryAssetOperations::DeleteOperation(cmd);
613 }
614 case OperationObject::PAH_FORM_MAP: {
615 return MediaLibraryFormMapOperations::RemoveFormIdOperations(rdbPredicate);
616 }
617 default:
618 break;
619 }
620
621 return DeleteInRdbPredicatesAnalysis(cmd, rdbPredicate);
622 }
623
DeleteInRdbPredicatesAnalysis(MediaLibraryCommand & cmd,NativeRdb::RdbPredicates & rdbPredicate)624 int32_t MediaLibraryDataManager::DeleteInRdbPredicatesAnalysis(MediaLibraryCommand &cmd,
625 NativeRdb::RdbPredicates &rdbPredicate)
626 {
627 switch (cmd.GetOprnObject()) {
628 case OperationObject::VISION_START ... OperationObject::VISION_END: {
629 return MediaLibraryVisionOperations::DeleteOperation(cmd);
630 }
631 case OperationObject::GEO_DICTIONARY:
632 case OperationObject::GEO_KNOWLEDGE:
633 case OperationObject::GEO_PHOTO: {
634 return MediaLibraryLocationOperations::DeleteOperation(cmd);
635 }
636 case OperationObject::SEARCH_TOTAL: {
637 return MediaLibrarySearchOperations::DeleteOperation(cmd);
638 }
639 default:
640 break;
641 }
642
643 return E_FAIL;
644 }
645
Update(MediaLibraryCommand & cmd,const DataShareValuesBucket & dataShareValue,const DataSharePredicates & predicates)646 int32_t MediaLibraryDataManager::Update(MediaLibraryCommand &cmd, const DataShareValuesBucket &dataShareValue,
647 const DataSharePredicates &predicates)
648 {
649 MEDIA_DEBUG_LOG("MediaLibraryDataManager::Update");
650 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
651 if (refCnt_.load() <= 0) {
652 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
653 return E_FAIL;
654 }
655
656 ValuesBucket value = RdbUtils::ToValuesBucket(dataShareValue);
657 if (value.IsEmpty()) {
658 MEDIA_ERR_LOG("MediaLibraryDataManager Update:Input parameter is invalid ");
659 return E_INVALID_VALUES;
660 }
661
662 #ifdef MEDIALIBRARY_COMPATIBILITY
663 ChangeUriFromValuesBucket(value);
664 #endif
665
666 cmd.SetValueBucket(value);
667 cmd.SetDataSharePred(predicates);
668 // MEDIALIBRARY_TABLE just for RdbPredicates
669 NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(predicates,
670 cmd.GetTableName());
671 cmd.GetAbsRdbPredicates()->SetWhereClause(rdbPredicate.GetWhereClause());
672 cmd.GetAbsRdbPredicates()->SetWhereArgs(rdbPredicate.GetWhereArgs());
673 return UpdateInternal(cmd, value, predicates);
674 }
675
UpdateInternal(MediaLibraryCommand & cmd,NativeRdb::ValuesBucket & value,const DataShare::DataSharePredicates & predicates)676 int32_t MediaLibraryDataManager::UpdateInternal(MediaLibraryCommand &cmd, NativeRdb::ValuesBucket &value,
677 const DataShare::DataSharePredicates &predicates)
678 {
679 switch (cmd.GetOprnObject()) {
680 case OperationObject::FILESYSTEM_ASSET: {
681 auto ret = MediaLibraryFileOperations::ModifyFileOperation(cmd);
682 if (ret == E_SAME_PATH) {
683 break;
684 } else {
685 return ret;
686 }
687 }
688 case OperationObject::FILESYSTEM_DIR:
689 // supply a ModifyDirOperation here to replace
690 // modify in the HandleDirOperations in Insert function, if need
691 break;
692 case OperationObject::FILESYSTEM_ALBUM: {
693 return MediaLibraryAlbumOperations::ModifyAlbumOperation(cmd);
694 }
695 case OperationObject::FILESYSTEM_PHOTO:
696 case OperationObject::FILESYSTEM_AUDIO: {
697 return MediaLibraryAssetOperations::UpdateOperation(cmd);
698 }
699 case OperationObject::ANALYSIS_PHOTO_ALBUM: {
700 if (cmd.GetOprnType() >= OperationType::PORTRAIT_DISPLAY_LEVEL &&
701 cmd.GetOprnType() <= OperationType::PORTRAIT_COVER_URI) {
702 return MediaLibraryAlbumOperations::HandleAnalysisPhotoAlbum(cmd.GetOprnType(), value, predicates);
703 }
704 break;
705 }
706 case OperationObject::PHOTO_ALBUM: {
707 return MediaLibraryAlbumOperations::HandlePhotoAlbum(cmd.GetOprnType(), value, predicates);
708 }
709 case OperationObject::GEO_DICTIONARY:
710 case OperationObject::GEO_KNOWLEDGE: {
711 return MediaLibraryLocationOperations::UpdateOperation(cmd);
712 }
713 case OperationObject::PAH_MULTISTAGES_CAPTURE: {
714 if (cmd.GetOprnType() == OperationType::ADD_IMAGE) {
715 MultiStagesCaptureManager::GetInstance().HandleMultiStagesOperation(cmd, value.GetAll());
716 }
717 return E_OK;
718 }
719 default:
720 break;
721 }
722 // ModifyInfoByIdInDb can finish the default update of smartalbum and smartmap,
723 // so no need to distinct them in switch-case deliberately
724 cmd.SetValueBucket(value);
725 return MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd);
726 }
727
InterruptBgworker()728 void MediaLibraryDataManager::InterruptBgworker()
729 {
730 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
731 if (refCnt_.load() <= 0) {
732 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
733 return;
734 }
735
736 if (thumbnailService_ == nullptr) {
737 return;
738 }
739 thumbnailService_->InterruptBgworker();
740 shared_ptr<TrashAsyncTaskWorker> asyncWorker = TrashAsyncTaskWorker::GetInstance();
741 if (asyncWorker == nullptr) {
742 MEDIA_ERR_LOG("asyncWorker null");
743 return;
744 }
745 asyncWorker->Interrupt();
746 }
747
GenerateThumbnails()748 int32_t MediaLibraryDataManager::GenerateThumbnails()
749 {
750 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
751 if (refCnt_.load() <= 0) {
752 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
753 return E_FAIL;
754 }
755
756 if (thumbnailService_ == nullptr) {
757 return E_THUMBNAIL_SERVICE_NULLPTR;
758 }
759 return thumbnailService_->GenerateThumbnails();
760 }
761
CacheAging()762 static void CacheAging()
763 {
764 filesystem::path cacheDir(MEDIA_CACHE_DIR);
765 if (!filesystem::exists(cacheDir)) {
766 return;
767 }
768
769 std::error_code errCode;
770 time_t now = time(nullptr);
771 constexpr int thresholdSeconds = 7 * 24 * 60 * 60; // 7 days
772 for (const auto& entry : filesystem::recursive_directory_iterator(cacheDir)) {
773 const char* filePath = entry.path().string().c_str();
774 if (!entry.is_regular_file()) {
775 MEDIA_WARN_LOG("skip %{private}s, not regular file", filePath);
776 continue;
777 }
778
779 struct stat statInfo {};
780 if (stat(filePath, &statInfo) != 0) {
781 MEDIA_WARN_LOG("skip %{private}s when stat error, errno: %{public}d", filePath, errno);
782 continue;
783 }
784 time_t timeModified = statInfo.st_mtime;
785 double duration = difftime(now, timeModified); // diff in seconds
786 if (duration < thresholdSeconds) {
787 continue;
788 }
789
790 if (!filesystem::remove(entry.path(), errCode)) {
791 MEDIA_WARN_LOG("Failed to remove %{private}s, errCode: %{public}d", filePath, errCode.value());
792 }
793 }
794 }
795
DoAging()796 int32_t MediaLibraryDataManager::DoAging()
797 {
798 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
799 MEDIA_DEBUG_LOG("MediaLibraryDataManager::DoAging IN");
800 if (refCnt_.load() <= 0) {
801 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
802 return E_FAIL;
803 }
804
805 CacheAging(); // aging file in .cache
806
807 shared_ptr<TrashAsyncTaskWorker> asyncWorker = TrashAsyncTaskWorker::GetInstance();
808 if (asyncWorker == nullptr) {
809 MEDIA_ERR_LOG("asyncWorker null");
810 return E_FAIL;
811 }
812 asyncWorker->Init();
813 return E_OK;
814 }
815
816 #ifdef DISTRIBUTED
LcdDistributeAging()817 int32_t MediaLibraryDataManager::LcdDistributeAging()
818 {
819 MEDIA_DEBUG_LOG("MediaLibraryDataManager::LcdDistributeAging IN");
820 auto deviceInstance = MediaLibraryDevice::GetInstance();
821 if ((thumbnailService_ == nullptr) || (deviceInstance == nullptr)) {
822 return E_THUMBNAIL_SERVICE_NULLPTR;
823 }
824 int32_t result = E_SUCCESS;
825 vector<string> deviceUdids;
826 deviceInstance->QueryAllDeviceUdid(deviceUdids);
827 for (string &udid : deviceUdids) {
828 result = thumbnailService_->LcdDistributeAging(udid);
829 if (result != E_SUCCESS) {
830 MEDIA_ERR_LOG("LcdDistributeAging fail result is %{public}d", result);
831 break;
832 }
833 }
834 return result;
835 }
836
DistributeDeviceAging()837 int32_t MediaLibraryDataManager::DistributeDeviceAging()
838 {
839 MEDIA_DEBUG_LOG("MediaLibraryDataManager::DistributeDeviceAging IN");
840 auto deviceInstance = MediaLibraryDevice::GetInstance();
841 if ((thumbnailService_ == nullptr) || (deviceInstance == nullptr)) {
842 return E_FAIL;
843 }
844 int32_t result = E_FAIL;
845 vector<MediaLibraryDeviceInfo> deviceDataBaseList;
846 deviceInstance->QueryAgingDeviceInfos(deviceDataBaseList);
847 MEDIA_DEBUG_LOG("MediaLibraryDevice InitDeviceRdbStore deviceDataBaseList size = %{public}d",
848 (int) deviceDataBaseList.size());
849 for (MediaLibraryDeviceInfo deviceInfo : deviceDataBaseList) {
850 result = thumbnailService_->InvalidateDistributeThumbnail(deviceInfo.deviceUdid);
851 if (result != E_SUCCESS) {
852 MEDIA_ERR_LOG("invalidate fail %{public}d", result);
853 continue;
854 }
855 }
856 return result;
857 }
858 #endif
859
GetThumbnail(const string & uri)860 int MediaLibraryDataManager::GetThumbnail(const string &uri)
861 {
862 if (thumbnailService_ == nullptr) {
863 return E_THUMBNAIL_SERVICE_NULLPTR;
864 }
865 if (!uri.empty() && MediaLibraryObjectUtils::CheckUriPending(uri)) {
866 MEDIA_ERR_LOG("failed to get thumbnail, the file:%{private}s is pending", uri.c_str());
867 return E_FAIL;
868 }
869 return thumbnailService_->GetThumbnailFd(uri);
870 }
871
CreateThumbnailAsync(const string & uri,const string & path)872 void MediaLibraryDataManager::CreateThumbnailAsync(const string &uri, const string &path)
873 {
874 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
875 if (refCnt_.load() <= 0) {
876 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
877 return;
878 }
879
880 if (thumbnailService_ == nullptr) {
881 return;
882 }
883 if (!uri.empty()) {
884 if (MediaLibraryObjectUtils::CheckUriPending(uri)) {
885 MEDIA_ERR_LOG("failed to get thumbnail, the file:%{private}s is pending", uri.c_str());
886 return;
887 }
888 int32_t err = thumbnailService_->CreateThumbnail(uri, path);
889 if (err != E_SUCCESS) {
890 MEDIA_ERR_LOG("ThumbnailService CreateThumbnail failed : %{public}d", err);
891 }
892 }
893 }
894
Query(MediaLibraryCommand & cmd,const vector<string> & columns,const DataSharePredicates & predicates,int & errCode)895 shared_ptr<ResultSetBridge> MediaLibraryDataManager::Query(MediaLibraryCommand &cmd,
896 const vector<string> &columns, const DataSharePredicates &predicates, int &errCode)
897 {
898 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
899 if (refCnt_.load() <= 0) {
900 errCode = E_FAIL;
901 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
902 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
903 {KEY_OPT_TYPE, OptType::QUERY}};
904 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
905 return nullptr;
906 }
907
908 MediaLibraryTracer tracer;
909 tracer.Start("MediaLibraryDataManager::Query");
910 if (rdbStore_ == nullptr) {
911 errCode = E_FAIL;
912 MEDIA_ERR_LOG("Rdb Store is not initialized");
913 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
914 {KEY_OPT_TYPE, OptType::QUERY}};
915 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
916 return nullptr;
917 }
918
919 auto absResultSet = QueryRdb(cmd, columns, predicates, errCode);
920 if (absResultSet == nullptr) {
921 errCode = (errCode != E_OK) ? errCode : E_FAIL;
922 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
923 {KEY_OPT_TYPE, OptType::QUERY}};
924 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
925 return nullptr;
926 }
927 return RdbUtils::ToResultSetBridge(absResultSet);
928 }
929
930 #ifdef DISTRIBUTED
SyncPullThumbnailKeys(const Uri & uri)931 int32_t MediaLibraryDataManager::SyncPullThumbnailKeys(const Uri &uri)
932 {
933 if (MediaLibraryDevice::GetInstance() == nullptr || !MediaLibraryDevice::GetInstance()->IsHasActiveDevice()) {
934 return E_ERR;
935 }
936 if (kvStorePtr_ == nullptr) {
937 return E_ERR;
938 }
939
940 MediaLibraryCommand cmd(uri, OperationType::QUERY);
941 cmd.GetAbsRdbPredicates()->BeginWrap()->EqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_IMAGE))
942 ->Or()->EqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_VIDEO))->EndWrap()
943 ->And()->EqualTo(MEDIA_DATA_DB_DATE_TRASHED, to_string(0))
944 ->And()->NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, to_string(MEDIA_TYPE_ALBUM))
945 ->OrderByDesc(MEDIA_DATA_DB_DATE_ADDED);
946 vector<string> columns = { MEDIA_DATA_DB_THUMBNAIL, MEDIA_DATA_DB_LCD };
947 auto resultset = MediaLibraryFileOperations::QueryFileOperation(cmd, columns);
948 if (resultset == nullptr) {
949 return E_HAS_DB_ERROR;
950 }
951
952 vector<string> thumbnailKeys;
953 int count = 0;
954 while (resultset->GoToNextRow() == NativeRdb::E_OK && count < MAX_QUERY_THUMBNAIL_KEY_COUNT) {
955 string thumbnailKey =
956 get<string>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_THUMBNAIL, resultset, TYPE_STRING));
957 thumbnailKeys.push_back(thumbnailKey);
958 string lcdKey = get<string>(ResultSetUtils::GetValFromColumn(MEDIA_DATA_DB_LCD, resultset, TYPE_STRING));
959 thumbnailKeys.push_back(lcdKey);
960 count++;
961 }
962
963 if (thumbnailKeys.empty()) {
964 return E_NO_SUCH_FILE;
965 }
966 MediaLibrarySyncOperation::SyncPullKvstore(kvStorePtr_, thumbnailKeys,
967 MediaFileUtils::GetNetworkIdFromUri(uri.ToString()));
968 return E_SUCCESS;
969 }
970 #endif
971
972 static const map<OperationObject, string> QUERY_CONDITION_MAP {
973 { OperationObject::SMART_ALBUM, SMARTALBUM_DB_ID },
974 { OperationObject::SMART_ALBUM_MAP, SMARTALBUMMAP_DB_ALBUM_ID },
975 { OperationObject::FILESYSTEM_DIR, MEDIA_DATA_DB_ID },
976 { OperationObject::ALL_DEVICE, "" },
977 { OperationObject::ACTIVE_DEVICE, "" },
978 { OperationObject::ASSETMAP, "" },
979 { OperationObject::SMART_ALBUM_ASSETS, "" },
980 { OperationObject::BUNDLE_PERMISSION, "" },
981 };
982
CheckIsPortraitAlbum(MediaLibraryCommand & cmd)983 bool CheckIsPortraitAlbum(MediaLibraryCommand &cmd)
984 {
985 auto predicates = cmd.GetAbsRdbPredicates();
986 auto whereClause = predicates->GetWhereClause();
987 if (whereClause.find(USER_DISPLAY_LEVEL) != string::npos || whereClause.find(IS_ME) != string::npos) {
988 return true;
989 }
990 return false;
991 }
992
AddVirtualColumnsOfDateType(vector<string> & columns)993 static void AddVirtualColumnsOfDateType(vector<string> &columns)
994 {
995 vector<string> dateTypes = { MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_DATE_TRASHED, MEDIA_DATA_DB_DATE_MODIFIED };
996 vector<string> dateTypeSeconds = { MEDIA_DATA_DB_DATE_ADDED_TO_SECOND,
997 MEDIA_DATA_DB_DATE_TRASHED_TO_SECOND, MEDIA_DATA_DB_DATE_MODIFIED_TO_SECOND };
998 for (size_t i = 0; i < dateTypes.size(); i++) {
999 auto it = find(columns.begin(), columns.end(), dateTypes[i]);
1000 if (it != columns.end()) {
1001 columns.push_back(dateTypeSeconds[i]);
1002 }
1003 }
1004 }
1005
QuerySet(MediaLibraryCommand & cmd,const vector<string> & columns,const DataSharePredicates & predicates,int & errCode)1006 shared_ptr<NativeRdb::ResultSet> MediaLibraryDataManager::QuerySet(MediaLibraryCommand &cmd,
1007 const vector<string> &columns, const DataSharePredicates &predicates, int &errCode)
1008 {
1009 MediaLibraryTracer tracer;
1010 tracer.Start("QueryRdb");
1011 tracer.Start("CheckWhereClause");
1012 MEDIA_DEBUG_LOG("CheckWhereClause start %{public}s", cmd.GetUri().ToString().c_str());
1013 auto whereClause = predicates.GetWhereClause();
1014 if (!MediaLibraryCommonUtils::CheckWhereClause(whereClause)) {
1015 errCode = E_INVALID_VALUES;
1016 MEDIA_ERR_LOG("illegal query whereClause input %{private}s", whereClause.c_str());
1017 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
1018 {KEY_OPT_TYPE, OptType::QUERY}};
1019 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1020 return nullptr;
1021 }
1022 MEDIA_DEBUG_LOG("CheckWhereClause end");
1023 tracer.Finish();
1024
1025 cmd.SetDataSharePred(predicates);
1026 // MEDIALIBRARY_TABLE just for RdbPredicates
1027 NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(predicates,
1028 MEDIALIBRARY_TABLE);
1029 cmd.GetAbsRdbPredicates()->SetWhereClause(rdbPredicate.GetWhereClause());
1030 cmd.GetAbsRdbPredicates()->SetWhereArgs(rdbPredicate.GetWhereArgs());
1031 cmd.GetAbsRdbPredicates()->SetOrder(rdbPredicate.GetOrder());
1032 AddVirtualColumnsOfDateType(const_cast<vector<string> &>(columns));
1033
1034 shared_ptr<NativeRdb::ResultSet> queryResultSet;
1035 OperationObject oprnObject = cmd.GetOprnObject();
1036 auto it = QUERY_CONDITION_MAP.find(oprnObject);
1037 if (it != QUERY_CONDITION_MAP.end()) {
1038 queryResultSet = MediaLibraryObjectUtils::QueryWithCondition(cmd, columns, it->second);
1039 } else if (oprnObject == OperationObject::FILESYSTEM_ALBUM || oprnObject == OperationObject::MEDIA_VOLUME) {
1040 queryResultSet = MediaLibraryAlbumOperations::QueryAlbumOperation(cmd, columns);
1041 } else if (oprnObject == OperationObject::PHOTO_ALBUM) {
1042 queryResultSet = MediaLibraryAlbumOperations::QueryPhotoAlbum(cmd, columns);
1043 } else if (oprnObject == OperationObject::ANALYSIS_PHOTO_ALBUM && CheckIsPortraitAlbum(cmd)) {
1044 queryResultSet = MediaLibraryAlbumOperations::QueryPortraitAlbum(cmd, columns);
1045 } else if (oprnObject == OperationObject::PHOTO_MAP || oprnObject == OperationObject::ANALYSIS_PHOTO_MAP) {
1046 queryResultSet = PhotoMapOperations::QueryPhotoAssets(
1047 RdbUtils::ToPredicates(predicates, PhotoColumn::PHOTOS_TABLE), columns);
1048 } else if (oprnObject == OperationObject::FILESYSTEM_PHOTO || oprnObject == OperationObject::FILESYSTEM_AUDIO) {
1049 queryResultSet = MediaLibraryAssetOperations::QueryOperation(cmd, columns);
1050 } else if (oprnObject >= OperationObject::VISION_OCR && oprnObject <= OperationObject::ANALYSIS_PHOTO_ALBUM) {
1051 queryResultSet = MediaLibraryRdbStore::Query(RdbUtils::ToPredicates(predicates, cmd.GetTableName()), columns);
1052 } else if (oprnObject == OperationObject::SEARCH_TOTAL) {
1053 queryResultSet = MediaLibraryRdbStore::Query(RdbUtils::ToPredicates(predicates, cmd.GetTableName()), columns);
1054 } else {
1055 tracer.Start("QueryFile");
1056 queryResultSet = MediaLibraryFileOperations::QueryFileOperation(cmd, columns);
1057 }
1058 return queryResultSet;
1059 }
1060
QueryRdb(MediaLibraryCommand & cmd,const vector<string> & columns,const DataSharePredicates & predicates,int & errCode)1061 shared_ptr<NativeRdb::ResultSet> MediaLibraryDataManager::QueryRdb(MediaLibraryCommand &cmd,
1062 const vector<string> &columns, const DataSharePredicates &predicates, int &errCode)
1063 {
1064 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
1065 if (refCnt_.load() <= 0) {
1066 errCode = E_FAIL;
1067 VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, errCode},
1068 {KEY_OPT_TYPE, OptType::QUERY}};
1069 PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1070 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
1071 return nullptr;
1072 }
1073
1074 return QuerySet(cmd, columns, predicates, errCode);
1075 }
1076
1077 #ifdef DISTRIBUTED
QuerySync(const string & networkId,const string & tableName)1078 bool MediaLibraryDataManager::QuerySync(const string &networkId, const string &tableName)
1079 {
1080 if (networkId.empty() || tableName.empty()) {
1081 return false;
1082 }
1083
1084 OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
1085 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
1086 auto ret = deviceManager.GetLocalDeviceInfo(bundleName_, deviceInfo);
1087 if (ret != ERR_OK) {
1088 MEDIA_ERR_LOG("MediaLibraryDataManager QuerySync Failed to get local device info.");
1089 return false;
1090 }
1091
1092 if (networkId == string(deviceInfo.networkId)) {
1093 return true;
1094 }
1095
1096 int32_t syncStatus = DEVICE_SYNCSTATUSING;
1097 auto result = MediaLibraryDevice::GetInstance()->GetDeviceSyncStatus(networkId, tableName, syncStatus);
1098 if (result && syncStatus == DEVICE_SYNCSTATUS_COMPLETE) {
1099 return true;
1100 }
1101
1102 vector<string> devices = { networkId };
1103 MediaLibrarySyncOpts syncOpts;
1104 syncOpts.rdbStore = rdbStore_;
1105 syncOpts.table = tableName;
1106 syncOpts.bundleName = bundleName_;
1107 return MediaLibrarySyncOperation::SyncPullTable(syncOpts, devices);
1108 }
1109 #endif
1110
OpenFile(MediaLibraryCommand & cmd,const string & mode)1111 int32_t MediaLibraryDataManager::OpenFile(MediaLibraryCommand &cmd, const string &mode)
1112 {
1113 MediaLibraryTracer tracer;
1114 tracer.Start("MediaLibraryDataManager::OpenFile");
1115 auto oprnObject = cmd.GetOprnObject();
1116 if (oprnObject == OperationObject::FILESYSTEM_PHOTO || oprnObject == OperationObject::FILESYSTEM_AUDIO) {
1117 return MediaLibraryAssetOperations::OpenOperation(cmd, mode);
1118 }
1119
1120 #ifdef MEDIALIBRARY_COMPATIBILITY
1121 if (oprnObject != OperationObject::THUMBNAIL && oprnObject != OperationObject::THUMBNAIL_ASTC) {
1122 string opObject = MediaFileUri::GetPathFirstDentry(const_cast<Uri &>(cmd.GetUri()));
1123 if (opObject == IMAGE_ASSET_TYPE || opObject == VIDEO_ASSET_TYPE || opObject == URI_TYPE_PHOTO) {
1124 cmd.SetOprnObject(OperationObject::FILESYSTEM_PHOTO);
1125 return MediaLibraryAssetOperations::OpenOperation(cmd, mode);
1126 }
1127 if (opObject == AUDIO_ASSET_TYPE || opObject == URI_TYPE_AUDIO_V10) {
1128 cmd.SetOprnObject(OperationObject::FILESYSTEM_AUDIO);
1129 return MediaLibraryAssetOperations::OpenOperation(cmd, mode);
1130 }
1131 }
1132 #endif
1133
1134 return MediaLibraryObjectUtils::OpenFile(cmd, mode);
1135 }
1136
NotifyChange(const Uri & uri)1137 void MediaLibraryDataManager::NotifyChange(const Uri &uri)
1138 {
1139 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
1140 if (refCnt_.load() <= 0) {
1141 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
1142 return;
1143 }
1144
1145 if (extension_ == nullptr) {
1146 MEDIA_ERR_LOG("MediaLibraryDataManager::NotifyChange failed");
1147 return;
1148 }
1149
1150 extension_->NotifyChange(uri);
1151 }
1152
InitialiseThumbnailService(const shared_ptr<OHOS::AbilityRuntime::Context> & extensionContext)1153 int32_t MediaLibraryDataManager::InitialiseThumbnailService(
1154 const shared_ptr<OHOS::AbilityRuntime::Context> &extensionContext)
1155 {
1156 if (thumbnailService_ != nullptr) {
1157 return E_OK;
1158 }
1159 thumbnailService_ = ThumbnailService::GetInstance();
1160 if (thumbnailService_ == nullptr) {
1161 return E_THUMBNAIL_SERVICE_NULLPTR;
1162 }
1163 #ifdef DISTRIBUTED
1164 thumbnailService_->Init(rdbStore_, kvStorePtr_, extensionContext);
1165 #else
1166 thumbnailService_->Init(rdbStore_, extensionContext);
1167 #endif
1168 return E_OK;
1169 }
1170
InitACLPermission()1171 void MediaLibraryDataManager::InitACLPermission()
1172 {
1173 if (access(THUMB_DIR.c_str(), F_OK) == 0) {
1174 return;
1175 }
1176
1177 if (!MediaFileUtils::CreateDirectory(THUMB_DIR)) {
1178 MEDIA_ERR_LOG("Failed create thumbs Photo dir");
1179 return;
1180 }
1181
1182 if (Acl::AclSetDefault() != E_OK) {
1183 MEDIA_ERR_LOG("Failed to set the acl read permission for the thumbs Photo dir");
1184 }
1185 }
1186
OnScanFinished(const int32_t status,const string & uri,const string & path)1187 int32_t ScanFileCallback::OnScanFinished(const int32_t status, const string &uri, const string &path)
1188 {
1189 auto instance = MediaLibraryDataManager::GetInstance();
1190 if (instance != nullptr) {
1191 instance->CreateThumbnailAsync(uri, path);
1192 }
1193 return E_OK;
1194 }
1195
SetCmdBundleAndDevice(MediaLibraryCommand & outCmd)1196 int32_t MediaLibraryDataManager::SetCmdBundleAndDevice(MediaLibraryCommand &outCmd)
1197 {
1198 string clientBundle = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
1199 if (clientBundle.empty()) {
1200 MEDIA_ERR_LOG("GetClientBundleName failed");
1201 return E_GET_CLIENTBUNDLE_FAIL;
1202 }
1203 outCmd.SetBundleName(clientBundle);
1204 #ifdef DISTRIBUTED
1205 OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
1206 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
1207 int32_t ret = deviceManager.GetLocalDeviceInfo(bundleName_, deviceInfo);
1208 if (ret < 0) {
1209 MEDIA_ERR_LOG("GetLocalDeviceInfo ret = %{public}d", ret);
1210 } else {
1211 outCmd.SetDeviceName(deviceInfo.deviceName);
1212 }
1213 return ret;
1214 #endif
1215 return 0;
1216 }
1217
DoTrashAging(shared_ptr<int> countPtr)1218 int32_t MediaLibraryDataManager::DoTrashAging(shared_ptr<int> countPtr)
1219 {
1220 shared_ptr<int> smartAlbumTrashPtr = make_shared<int>();
1221 MediaLibrarySmartAlbumMapOperations::HandleAgingOperation(smartAlbumTrashPtr);
1222
1223 shared_ptr<int> albumTrashtPtr = make_shared<int>();
1224 MediaLibraryAlbumOperations::HandlePhotoAlbum(OperationType::AGING, {}, {}, albumTrashtPtr);
1225
1226 shared_ptr<int> audioTrashtPtr = make_shared<int>();
1227 MediaLibraryAudioOperations::TrashAging(audioTrashtPtr);
1228
1229 if (countPtr != nullptr) {
1230 *countPtr = *smartAlbumTrashPtr + *albumTrashtPtr + *audioTrashtPtr;
1231 }
1232 return E_SUCCESS;
1233 }
1234
RevertPendingByFileId(const std::string & fileId)1235 int32_t MediaLibraryDataManager::RevertPendingByFileId(const std::string &fileId)
1236 {
1237 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_ASSET, OperationType::UPDATE);
1238 ValuesBucket values;
1239 values.PutLong(Media::MEDIA_DATA_DB_TIME_PENDING, 0);
1240 cmd.SetValueBucket(values);
1241 int32_t retVal = MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd, fileId);
1242 if (retVal <= 0) {
1243 MEDIA_ERR_LOG("failed to revert pending error, fileId:%{private}s", fileId.c_str());
1244 return retVal;
1245 }
1246 auto fileAsset = MediaLibraryObjectUtils::GetFileAssetFromId(fileId);
1247 string srcPath = fileAsset->GetPath();
1248 MediaLibraryObjectUtils::ScanFileAsync(srcPath, fileId, MediaLibraryApi::API_10);
1249 return E_SUCCESS;
1250 }
1251
RevertPendingByPackage(const std::string & bundleName)1252 int32_t MediaLibraryDataManager::RevertPendingByPackage(const std::string &bundleName)
1253 {
1254 MediaLibraryCommand queryCmd(OperationObject::FILESYSTEM_ASSET, OperationType::QUERY);
1255 queryCmd.GetAbsRdbPredicates()
1256 ->EqualTo(MEDIA_DATA_DB_OWNER_PACKAGE, bundleName)
1257 ->And()
1258 ->NotEqualTo(MEDIA_DATA_DB_TIME_PENDING, to_string(0));
1259 vector<string> columns = { MEDIA_DATA_DB_ID };
1260 auto result = MediaLibraryObjectUtils::QueryWithCondition(queryCmd, columns);
1261 if (result == nullptr) {
1262 return E_HAS_DB_ERROR;
1263 }
1264
1265 int32_t ret = E_SUCCESS;
1266 while (result->GoToNextRow() == NativeRdb::E_OK) {
1267 int32_t id = GetInt32Val(MEDIA_DATA_DB_ID, result);
1268 int32_t retVal = RevertPendingByFileId(to_string(id));
1269 if (retVal != E_SUCCESS) {
1270 ret = retVal;
1271 MEDIA_ERR_LOG("Revert file %{public}d failed, ret=%{public}d", id, retVal);
1272 continue;
1273 }
1274 }
1275 return ret;
1276 }
1277
1278
GetAgingDataSize(const int64_t & time,int & count)1279 int32_t MediaLibraryDataManager::GetAgingDataSize(const int64_t &time, int &count)
1280 {
1281 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
1282 if (refCnt_.load() <= 0) {
1283 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
1284 return E_FAIL;
1285 }
1286
1287 if (thumbnailService_ == nullptr) {
1288 return E_THUMBNAIL_SERVICE_NULLPTR;
1289 }
1290 return thumbnailService_->GetAgingDataSize(time, count);
1291 }
1292
1293
QueryNewThumbnailCount(const int64_t & time,int & count)1294 int32_t MediaLibraryDataManager::QueryNewThumbnailCount(const int64_t &time, int &count)
1295 {
1296 shared_lock<shared_mutex> sharedLock(mgrSharedMutex_);
1297 if (refCnt_.load() <= 0) {
1298 MEDIA_DEBUG_LOG("MediaLibraryDataManager is not initialized");
1299 return E_FAIL;
1300 }
1301
1302 if (thumbnailService_ == nullptr) {
1303 return E_THUMBNAIL_SERVICE_NULLPTR;
1304 }
1305 return thumbnailService_->QueryNewThumbnailCount(time, count);
1306 }
1307
1308 class DownloadCloudFilesData : public AsyncTaskData {
1309 public:
1310 DownloadCloudFilesData() = default;
1311 ~DownloadCloudFilesData() override = default;
1312
1313 vector<string> paths;
1314 };
1315
DownloadCloudFilesExecutor(AsyncTaskData * data)1316 static void DownloadCloudFilesExecutor(AsyncTaskData* data)
1317 {
1318 auto *taskData = static_cast<DownloadCloudFilesData *>(data);
1319
1320 MEDIA_DEBUG_LOG("Try to download %{public}zu cloud files.", taskData->paths.size());
1321 for (const auto &path : taskData->paths) {
1322 CloudSyncHelper::GetInstance()->StartDownloadFile(path);
1323 }
1324 }
1325
AddDownloadTask(const vector<string> & photoPaths)1326 static int32_t AddDownloadTask(const vector<string> &photoPaths)
1327 {
1328 auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
1329 if (asyncWorker == nullptr) {
1330 MEDIA_ERR_LOG("Failed to get async worker instance!");
1331 return E_FAIL;
1332 }
1333 auto *taskData = new (nothrow)DownloadCloudFilesData();
1334 if (taskData == nullptr) {
1335 MEDIA_ERR_LOG("Failed to alloc async data for downloading cloud files!");
1336 return E_NO_MEMORY;
1337 }
1338 taskData->paths = photoPaths;
1339 auto asyncTask = make_shared<MediaLibraryAsyncTask>(DownloadCloudFilesExecutor, taskData);
1340 asyncWorker->AddTask(asyncTask, false);
1341 return E_OK;
1342 }
1343
QueryCloudFiles()1344 static shared_ptr<NativeRdb::ResultSet> QueryCloudFiles()
1345 {
1346 const vector<string> photosType = {
1347 to_string(MEDIA_TYPE_IMAGE),
1348 to_string(MEDIA_TYPE_VIDEO)
1349 };
1350 const vector<string> columns = {
1351 PhotoColumn::MEDIA_FILE_PATH
1352 };
1353
1354 RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1355 predicates.EqualTo(PhotoColumn::PHOTO_POSITION, to_string(POSITION_CLOUD));
1356 predicates.In(PhotoColumn::MEDIA_TYPE, photosType);
1357 predicates.Limit(DOWNLOAD_BATCH_SIZE);
1358 return MediaLibraryRdbStore::Query(predicates, columns);
1359 }
1360
FillPhotoPaths(shared_ptr<NativeRdb::ResultSet> & resultSet,vector<string> & photoPaths)1361 static void FillPhotoPaths(shared_ptr<NativeRdb::ResultSet> &resultSet, vector<string> &photoPaths)
1362 {
1363 string path;
1364 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1365 path = get<string>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_FILE_PATH, resultSet, TYPE_STRING));
1366 if (path.empty()) {
1367 MEDIA_WARN_LOG("Failed to get cloud file uri!");
1368 continue;
1369 }
1370 photoPaths.push_back(path);
1371 }
1372 }
1373
NeedDownloadCloudFiles()1374 static bool NeedDownloadCloudFiles()
1375 {
1376 const vector<string> localPositions = {
1377 to_string(POSITION_LOCAL),
1378 to_string((POSITION_LOCAL | POSITION_CLOUD)),
1379 };
1380 const vector<string> photosType = {
1381 to_string(MEDIA_TYPE_IMAGE),
1382 to_string(MEDIA_TYPE_VIDEO)
1383 };
1384 RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1385 predicates.In(PhotoColumn::PHOTO_POSITION, localPositions);
1386 predicates.In(PhotoColumn::MEDIA_TYPE, photosType);
1387 auto resultSet = MediaLibraryRdbStore::Query(predicates, { PhotoColumn::MEDIA_ID });
1388 if (resultSet == nullptr) {
1389 MEDIA_ERR_LOG("Failed to query local files!");
1390 return false;
1391 }
1392 int32_t count = 0;
1393 int32_t err = resultSet->GetRowCount(count);
1394 if (err != NativeRdb::E_OK) {
1395 MEDIA_ERR_LOG("Failed to get count, err: %{public}d", err);
1396 return false;
1397 }
1398 return count <= LOCAL_FILES_COUNT_THRESHOLD;
1399 }
1400
DownloadCloudFiles()1401 static void DownloadCloudFiles()
1402 {
1403 if (!NeedDownloadCloudFiles()) {
1404 return;
1405 }
1406 vector<string> photoPaths;
1407 auto resultSet = QueryCloudFiles();
1408 if (resultSet == nullptr) {
1409 MEDIA_ERR_LOG("Failed to query cloud files!");
1410 return;
1411 }
1412 FillPhotoPaths(resultSet, photoPaths);
1413 if (photoPaths.empty()) {
1414 MEDIA_DEBUG_LOG("No cloud photos exist, no need to download");
1415 return;
1416 }
1417 int32_t err = AddDownloadTask(photoPaths);
1418 if (err) {
1419 MEDIA_WARN_LOG("Failed to add download task! err: %{public}d", err);
1420 }
1421 }
1422
RegisterTimer()1423 void MediaLibraryDataManager::RegisterTimer()
1424 {
1425 UnregisterTimer();
1426 timerId_ = timer_.Register(DownloadCloudFiles, BATCH_DOWNLOAD_INTERVAL);
1427 timer_.Setup();
1428 }
1429
StopTimer()1430 void MediaLibraryDataManager::StopTimer()
1431 {
1432 timer_.Shutdown();
1433 }
1434
UnregisterTimer()1435 void MediaLibraryDataManager::UnregisterTimer()
1436 {
1437 timer_.Shutdown();
1438 timer_.Unregister(timerId_);
1439 }
1440 } // namespace Media
1441 } // namespace OHOS
1442