1 /*
2 * Copyright (C) 2021 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 #include "medialibrary_data_ability.h"
17
18 #include <algorithm>
19 #include <regex>
20 #include <unordered_set>
21
22 #include "accesstoken_kit.h"
23 #include "bytrace.h"
24 #include "bundle_mgr_interface.h"
25 #include "file_ex.h"
26 #include "ipc_singleton.h"
27 #include "ipc_skeleton.h"
28 #include "sa_mgr_client.h"
29 #include "string_ex.h"
30 #include "sys_mgr_client.h"
31 #include "system_ability_definition.h"
32 #include "medialibrary_sync_table.h"
33
34 using namespace std;
35 using namespace OHOS::AppExecFwk;
36 using namespace OHOS::NativeRdb;
37 using namespace OHOS::DistributedKv;
38
39 namespace OHOS {
40 namespace Media {
41 namespace {
42 const std::unordered_set<int32_t> UID_FREE_CHECK {
43 1006 // file_manager:x:1006:
44 };
45 const std::unordered_set<std::string> BUNDLE_FREE_CHECK {
46 "com.ohos.medialibrary.MediaScannerAbilityA"
47 };
48 const std::unordered_set<std::string> SYSTEM_BUNDLE_FREE_CHECK {
49 "com.ohos.screenshot"
50 };
51 std::mutex bundleMgrMutex;
52 }
53 const std::string MediaLibraryDataAbility::PERMISSION_NAME_READ_MEDIA = "ohos.permission.READ_MEDIA";
54 const std::string MediaLibraryDataAbility::PERMISSION_NAME_WRITE_MEDIA = "ohos.permission.WRITE_MEDIA";
55 REGISTER_AA(MediaLibraryDataAbility);
56
57 const std::vector<std::string> fileKeyWhiteListUSet = {
58 MEDIA_DATA_DB_ID,
59 MEDIA_DATA_DB_URI,
60 MEDIA_DATA_DB_FILE_PATH,
61 MEDIA_DATA_DB_SIZE,
62 MEDIA_DATA_DB_PARENT_ID,
63 MEDIA_DATA_DB_DATE_MODIFIED,
64 MEDIA_DATA_DB_DATE_ADDED,
65 MEDIA_DATA_DB_MIME_TYPE,
66 MEDIA_DATA_DB_TITLE,
67 MEDIA_DATA_DB_DESCRIPTION,
68 MEDIA_DATA_DB_NAME,
69 MEDIA_DATA_DB_ORIENTATION,
70 MEDIA_DATA_DB_LATITUDE,
71 MEDIA_DATA_DB_LONGITUDE,
72 MEDIA_DATA_DB_DATE_TAKEN,
73 MEDIA_DATA_DB_THUMBNAIL,
74 MEDIA_DATA_DB_LCD,
75 MEDIA_DATA_DB_BUCKET_ID,
76 MEDIA_DATA_DB_BUCKET_NAME,
77 MEDIA_DATA_DB_DURATION,
78 MEDIA_DATA_DB_ARTIST,
79 MEDIA_DATA_DB_AUDIO_ALBUM,
80 MEDIA_DATA_DB_MEDIA_TYPE,
81 MEDIA_DATA_DB_HEIGHT,
82 MEDIA_DATA_DB_WIDTH,
83 MEDIA_DATA_DB_OWNER_PACKAGE,
84 MEDIA_DATA_DB_IS_FAV,
85 MEDIA_DATA_DB_IS_TRASH,
86 MEDIA_DATA_DB_DATE_TRASHED,
87 MEDIA_DATA_DB_IS_PENDING,
88 MEDIA_DATA_DB_TIME_PENDING,
89 MEDIA_DATA_DB_RELATIVE_PATH,
90 MEDIA_DATA_DB_VOLUME_NAME,
91 MEDIA_DATA_DB_SELF_ID,
92 MEDIA_DATA_DB_ALBUM,
93 MEDIA_DATA_DB_ALBUM_ID,
94 MEDIA_DATA_DB_ALBUM_NAME,
95 MEDIA_DATA_DB_COUNT,
96 MEDIA_DATA_DB_RINGTONE_URI,
97 MEDIA_DATA_DB_ALARM_URI,
98 MEDIA_DATA_DB_NOTIFICATION_URI,
99 MEDIA_DATA_DB_RINGTONE_TYPE
100 };
101
OnStart(const AAFwk::Want & want)102 void MediaLibraryDataAbility::OnStart(const AAFwk::Want &want)
103 {
104 MEDIA_INFO_LOG("MediaLibraryDataAbility::OnStart");
105 Ability::OnStart(want);
106 InitMediaLibraryRdbStore();
107 MEDIA_INFO_LOG("bundleName = %{public}s", bundleName_.c_str());
108 auto abilityContext = std::make_unique<MediaLibraryDataAbility>(*this);
109 if (abilityContext != nullptr) {
110 MediaLibraryDevice::GetInstance()->SetAbilityContext(move(abilityContext));
111 }
112 SubscribeRdbStoreObserver();
113 InitDeviceData();
114
115 if (rdbStore_ != nullptr) {
116 MEDIA_DEBUG_LOG("Distribute StartTrace:SyncPullAllTableTrace");
117 StartTrace(BYTRACE_TAG_OHOS, "SyncPullAllTableTrace");
118 MediaLibrarySyncTable syncTable;
119 syncTable.SyncPullAllTable(rdbStore_, bundleName_);
120 FinishTrace(BYTRACE_TAG_OHOS);
121 MEDIA_DEBUG_LOG("Distribute FinishTrace:SyncPullAllTableTrace");
122 }
123 InitialiseKvStore();
124 }
125
OnStop()126 void MediaLibraryDataAbility::OnStop()
127 {
128 MEDIA_INFO_LOG("MediaLibraryDataAbility::OnStop");
129 Ability::OnStop();
130 rdbStore_ = nullptr;
131 isRdbStoreInitialized = false;
132
133 if (scannerClient_ != nullptr) {
134 scannerClient_->Release();
135 scannerClient_ = nullptr;
136 }
137
138 if (kvStorePtr_ != nullptr) {
139 dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
140 kvStorePtr_ = nullptr;
141 }
142 if (deviceStateCallback_ != nullptr && deviceInitCallback_ != nullptr) {
143 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
144 deviceManager.UnInitDeviceManager(bundleName_);
145 deviceInitCallback_ = nullptr;
146 deviceManager.UnRegisterDevStateCallback(bundleName_);
147 deviceStateCallback_ = nullptr;
148 MediaLibraryDevice::GetInstance()->ClearAllDevices();
149 }
150 UnSubscribeRdbStoreObserver();
151 }
152
MediaLibraryDataAbility(void)153 MediaLibraryDataAbility::MediaLibraryDataAbility(void)
154 {
155 isRdbStoreInitialized = false;
156 rdbStore_ = nullptr;
157 kvStorePtr_ = nullptr;
158 bundleName_ = DEVICE_BUNDLENAME;
159 }
160
~MediaLibraryDataAbility(void)161 MediaLibraryDataAbility::~MediaLibraryDataAbility(void)
162 {
163 if (kvStorePtr_ != nullptr) {
164 dataManager_.CloseKvStore(KVSTORE_APPID, kvStorePtr_);
165 kvStorePtr_ = nullptr;
166 }
167 }
168
OnCreate(RdbStore & store)169 int32_t MediaLibraryDataCallBack::OnCreate(RdbStore &store)
170 {
171 int32_t error_code = NativeRdb::E_ERROR;
172 error_code = store.ExecuteSql(CREATE_MEDIA_TABLE);
173 if (error_code == NativeRdb::E_OK) {
174 error_code = store.ExecuteSql(CREATE_SMARTALBUM_TABLE);
175 }
176 if (error_code == NativeRdb::E_OK) {
177 error_code = store.ExecuteSql(CREATE_SMARTALBUMMAP_TABLE);
178 }
179 if (error_code == NativeRdb::E_OK) {
180 error_code = store.ExecuteSql(CREATE_DEVICE_TABLE);
181 }
182 if (error_code == NativeRdb::E_OK) {
183 error_code = store.ExecuteSql(CREATE_CATEGORY_SMARTALBUMMAP_TABLE);
184 }
185 if (error_code == NativeRdb::E_OK) {
186 error_code = store.ExecuteSql(CREATE_IMAGE_VIEW);
187 }
188 if (error_code == NativeRdb::E_OK) {
189 error_code = store.ExecuteSql(CREATE_VIDEO_VIEW);
190 }
191 if (error_code == NativeRdb::E_OK) {
192 error_code = store.ExecuteSql(CREATE_AUDIO_VIEW);
193 }
194 if (error_code == NativeRdb::E_OK) {
195 error_code= store.ExecuteSql(CREATE_ABLUM_VIEW);
196 }
197 if (error_code == NativeRdb::E_OK) {
198 error_code= store.ExecuteSql(CREATE_SMARTABLUMASSETS_VIEW);
199 }
200 if (error_code == NativeRdb::E_OK) {
201 error_code= store.ExecuteSql(CREATE_ASSETMAP_VIEW);
202 }
203 if (error_code == NativeRdb::E_OK) {
204 isDistributedTables = true;
205 }
206 return error_code;
207 }
208
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)209 int32_t MediaLibraryDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
210 {
211 #ifdef RDB_UPGRADE_MOCK
212 const std::string ALTER_MOCK_COLUMN = "ALTER TABLE " + MEDIALIBRARY_TABLE +
213 " ADD COLUMN upgrade_test_column INT DEFAULT 0";
214 MEDIA_INFO_LOG("OnUpgrade |Rdb Verison %{public}d => %{public}d", oldVersion, newVersion);
215 int32_t error_code = NativeRdb::E_ERROR;
216 error_code = store.ExecuteSql(ALTER_MOCK_COLUMN);
217 if (error_code != NativeRdb::E_OK) {
218 MEDIA_INFO_LOG("Upgrade rdb error %{public}d", error_code);
219 }
220 #endif
221 return E_OK;
222 }
223
GetDistributedTables()224 bool MediaLibraryDataCallBack::GetDistributedTables()
225 {
226 return isDistributedTables;
227 }
228
InitMediaLibraryRdbStore()229 int32_t MediaLibraryDataAbility::InitMediaLibraryRdbStore()
230 {
231 MEDIA_INFO_LOG("InitMediaLibraryRdbStore IN |Rdb Verison %{public}d", MEDIA_RDB_VERSION);
232 if (isRdbStoreInitialized) {
233 return DATA_ABILITY_SUCCESS;
234 }
235
236 int32_t errCode(DATA_ABILITY_FAIL);
237 auto context = GetAbilityContext();
238 if (context == nullptr) {
239 MEDIA_ERR_LOG("InitMediaRdbStore context is nullptr");
240 return errCode;
241 }
242
243 string databaseDir = context->GetDatabaseDir();
244 string relativePath = MEDIA_DATA_ABILITY_DB_NAME;
245
246 RdbStoreConfig config(databaseDir + "/" + relativePath);
247 config.SetBundleName(context->GetBundleName());
248 config.SetName(MEDIA_DATA_ABILITY_DB_NAME);
249 config.SetRelativePath(relativePath);
250 config.SetEncryptLevel(ENCRYPTION_LEVEL);
251 config.SetAppModuleName(context->GetHapModuleInfo()->moduleName);
252
253 MediaLibraryDataCallBack rdbDataCallBack;
254
255 rdbStore_ = RdbHelper::GetRdbStore(config, MEDIA_RDB_VERSION, rdbDataCallBack, errCode);
256 if (rdbStore_ == nullptr) {
257 MEDIA_ERR_LOG("InitMediaRdbStore GetRdbStore is failed ");
258 return errCode;
259 }
260
261 if (rdbDataCallBack.GetDistributedTables()) {
262 auto ret = rdbStore_->SetDistributedTables(
263 {MEDIALIBRARY_TABLE, SMARTALBUM_TABLE, SMARTALBUM_MAP_TABLE, CATEGORY_SMARTALBUM_MAP_TABLE});
264 MEDIA_INFO_LOG("InitMediaLibraryRdbStore ret = %{public}d", ret);
265 }
266
267 isRdbStoreInitialized = true;
268 mediaThumbnail_ = std::make_shared<MediaLibraryThumbnail>();
269 MEDIA_INFO_LOG("InitMediaLibraryRdbStore SUCCESS");
270 return DATA_ABILITY_SUCCESS;
271 }
272
ExtractKeyWord(std::string & str)273 static void ExtractKeyWord(std::string &str)
274 {
275 if (str.empty()) {
276 return;
277 }
278 // add seprate space symbol,like file_id=?
279 std::regex spacePattern("\\=|\\<>|\\>|\\>=|\\<|\\<=|\\!=",
280 std::regex_constants::ECMAScript | std::regex_constants::icase);
281 str = regex_replace(str, spacePattern, " ");
282 // remove front space of key word
283 auto pos = str.find_first_not_of(" ");
284 if (pos != std::string::npos) {
285 str.erase(0, pos);
286 }
287 // remove back space of key word
288 pos = str.find_first_of(" ");
289 if (pos != std::string::npos) {
290 str = str.substr(0, pos);
291 }
292 }
293
CheckWhiteList(const std::string & express)294 static bool CheckWhiteList(const std::string &express)
295 {
296 auto it = std::find_if(fileKeyWhiteListUSet.begin(), fileKeyWhiteListUSet.end(), [express](const std::string &str) {
297 return express.find(str) != string::npos;
298 });
299 if (it != fileKeyWhiteListUSet.end()) {
300 return true;
301 }
302 MEDIA_ERR_LOG("Failed to check express: %{private}s", express.c_str());
303
304 return false;
305 }
306
CheckExpressValidation(std::vector<std::string> & sepratedStr)307 static bool CheckExpressValidation(std::vector<std::string> &sepratedStr)
308 {
309 for (auto &str : sepratedStr) {
310 ExtractKeyWord(str);
311 if (str.empty() || (str.size() == 1 && str == " ")) {
312 continue;
313 }
314 if (!CheckWhiteList(str)) {
315 return false;
316 }
317 }
318
319 return true;
320 }
321
removeSpecialCondition(std::string & hacker,const std::string & pattern)322 static void removeSpecialCondition(std::string &hacker, const std::string &pattern)
323 {
324 auto pos = hacker.find(pattern);
325 while (pos != std::string::npos) {
326 hacker.replace(pos, pos + pattern.size(), " ");
327 pos = hacker.find(pattern);
328 }
329 }
330
removeSpecialCondition(std::string & hacker)331 static void removeSpecialCondition(std::string &hacker)
332 {
333 const std::string S1 = "not between ? and ?";
334 const std::string S2 = "between ? and ?";
335 removeSpecialCondition(hacker, S1);
336 removeSpecialCondition(hacker, S2);
337 }
338
SeprateSelection(std::string & strCondition,std::vector<std::string> & sepratedStr)339 static void SeprateSelection(std::string &strCondition, std::vector<std::string> &sepratedStr)
340 {
341 // 0. transform to lower
342 std::transform(strCondition.begin(), strCondition.end(), strCondition.begin(), ::tolower);
343 // 1.remove brackets
344 std::regex bracketsPattern("\\(|\\)", std::regex_constants::ECMAScript | std::regex_constants::icase);
345 strCondition = regex_replace(strCondition, bracketsPattern, "");
346
347 // 2.remove redundant space
348 std::regex spacePattern("\\s+", std::regex_constants::ECMAScript | std::regex_constants::icase);
349 strCondition = regex_replace(strCondition, spacePattern, " ");
350
351 // 3. remove special condition
352 removeSpecialCondition(strCondition);
353
354 // 4. seprate core: according bound symbol,for example: and or ..
355 std::regex conditionPattern("\\s*and\\s+|\\s*or\\s+",
356 std::regex_constants::ECMAScript | std::regex_constants::icase);
357 std::sregex_token_iterator iter(strCondition.begin(), strCondition.end(), conditionPattern, -1);
358 decltype(iter) end;
359 while (iter != end) {
360 sepratedStr.push_back(iter->str());
361 ++iter;
362 }
363 }
364
CheckKeyWord(const std::string & strCondition)365 static bool CheckKeyWord(const std::string &strCondition)
366 {
367 std::regex pattern("\\s*exec\\s*|\\s*insert\\s*|\\s*delete\\s*|\\s*update\\s*|" \
368 "\\s*join\\s*|\\s*union\\s*|\\s*master\\s*|\\s*truncate\\s*",
369 std::regex_constants::ECMAScript | std::regex_constants::icase);
370
371 if (regex_search(strCondition, pattern)) {
372 MEDIA_ERR_LOG("Faild to check key word");
373 return false;
374 }
375
376 return true;
377 }
378
CheckIllegalCharacter(const std::string & strCondition)379 static bool CheckIllegalCharacter(const std::string &strCondition)
380 {
381 /* if strCondition contains ';', it will be sepreate to two clause */
382 if (strCondition.find(';') == std::string::npos) {
383 return true;
384 }
385 MEDIA_ERR_LOG("Faild to check illegal character");
386 /* other check to do */
387 return false;
388 }
389
CheckWhereClause(const std::string & whereClause)390 static bool CheckWhereClause(const std::string &whereClause)
391 {
392 if (whereClause.empty() || (whereClause.size() == 1 && whereClause == " ")) {
393 return true;
394 }
395
396 /* check whether query condition has illegal character */
397 if (!CheckIllegalCharacter(whereClause)) {
398 return false;
399 }
400
401 /* check whether query condition has key word */
402 if (!CheckKeyWord(whereClause)) {
403 return false;
404 }
405
406 std::vector<std::string> sepratedStr;
407 auto args = whereClause;
408 SeprateSelection(args, sepratedStr);
409 /* check every query condition */
410 return CheckExpressValidation(sepratedStr);
411 }
412
GetType(const Uri & uri)413 std::string MediaLibraryDataAbility::GetType(const Uri &uri)
414 {
415 string getTypeUri = uri.ToString();
416 // If get uri contains media operation keyword, follow media operation procedure
417 if (getTypeUri.find(MEDIA_OPERN_KEYWORD) != string::npos) {
418 MediaLibraryKvStoreOperations kvStoreOprn;
419
420 if (getTypeUri.find(MEDIA_KVSTOREOPRN) != string::npos) {
421 return kvStoreOprn.HandleKvStoreGetOperations(getTypeUri, kvStorePtr_);
422 }
423 }
424 return "";
425 }
426
PreCheckInsert(const string & uri,const ValuesBucket & value)427 int32_t MediaLibraryDataAbility::PreCheckInsert(const string &uri, const ValuesBucket &value)
428 {
429 if ((!isRdbStoreInitialized) || (value.IsEmpty()) || (rdbStore_ == nullptr)) {
430 MEDIA_ERR_LOG("MediaLibraryDataAbility Insert: Input parameter is invalid");
431 return DATA_ABILITY_FAIL;
432 }
433
434 string tmpUri = MEDIALIBRARY_DATA_URI + "/" + MEDIA_FILEOPRN + "/" + MEDIA_FILEOPRN_CLOSEASSET;
435 if (uri == tmpUri) {
436 if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA)) {
437 return DATA_ABILITY_PERMISSION_DENIED;
438 }
439 } else if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
440 return DATA_ABILITY_PERMISSION_DENIED;
441 }
442 return DATA_ABILITY_SUCCESS;
443 }
444
Insert(const Uri & uri,const ValuesBucket & value)445 int32_t MediaLibraryDataAbility::Insert(const Uri &uri, const ValuesBucket &value)
446 {
447 string insertUri = uri.ToString();
448 auto result = PreCheckInsert(insertUri, value);
449 if (result) {
450 return result;
451 }
452
453 MediaLibrarySyncTable syncTable;
454 std::vector<std::string> devices = std::vector<std::string>();
455 // If insert uri contains media opearation, follow media operation procedure
456 if (insertUri.find(MEDIA_OPERN_KEYWORD) != string::npos) {
457 MediaLibraryFileOperations fileOprn;
458 MediaLibraryAlbumOperations albumOprn;
459 MediaLibrarySmartAlbumOperations smartalbumOprn;
460 MediaLibrarySmartAlbumMapOperations smartalbumMapOprn;
461 MediaLibraryKvStoreOperations kvStoreOprn;
462
463 result = DATA_ABILITY_FAIL;
464 string operationType = MediaLibraryDataAbilityUtils::GetOperationType(insertUri);
465 MEDIA_INFO_LOG("operationType = %{public}s", operationType.c_str());
466 if ((operationType == MEDIA_FILEOPRN_CREATEASSET ||
467 operationType == MEDIA_ALBUMOPRN_CREATEALBUM) && !CheckFileNameValid(value)) {
468 return DATA_ABILITY_FILE_NAME_INVALID;
469 }
470 if (insertUri.find(MEDIA_FILEOPRN) != string::npos) {
471 result = fileOprn.HandleFileOperation(operationType, value, rdbStore_, mediaThumbnail_);
472 // After successfull close asset operation, do a scan file
473 if ((result >= 0) && (operationType == MEDIA_FILEOPRN_CLOSEASSET)) {
474 ScanFile(value, rdbStore_);
475 }
476 syncTable.SyncPushTable(rdbStore_, bundleName_, MEDIALIBRARY_TABLE, devices);
477 } else if (insertUri.find(MEDIA_ALBUMOPRN) != string::npos) {
478 result = albumOprn.HandleAlbumOperations(operationType, value, rdbStore_);
479 syncTable.SyncPushTable(rdbStore_, bundleName_, SMARTALBUM_TABLE, devices);
480 } else if (insertUri.find(MEDIA_SMARTALBUMOPRN) != string::npos) {
481 result = smartalbumOprn.HandleSmartAlbumOperations(operationType, value, rdbStore_);
482 syncTable.SyncPushTable(rdbStore_, bundleName_, SMARTALBUM_MAP_TABLE, devices);
483 } else if (insertUri.find(MEDIA_SMARTALBUMMAPOPRN) != string::npos) {
484 result = smartalbumMapOprn.HandleSmartAlbumMapOperations(operationType, value, rdbStore_);
485 syncTable.SyncPushTable(rdbStore_, bundleName_, CATEGORY_SMARTALBUM_MAP_TABLE, devices);
486 } else if (insertUri.find(MEDIA_KVSTOREOPRN) != string::npos) {
487 result = kvStoreOprn.HandleKvStoreInsertOperations(operationType, value, kvStorePtr_);
488 }
489 return result;
490 }
491
492 // Normal URI scenario
493 int64_t outRowId = DATA_ABILITY_FAIL;
494 (void)rdbStore_->Insert(outRowId, MEDIALIBRARY_TABLE, value);
495
496 syncTable.SyncPushTable(rdbStore_, bundleName_, MEDIALIBRARY_TABLE, devices);
497 return outRowId;
498 }
499
Delete(const Uri & uri,const DataAbilityPredicates & predicates)500 int32_t MediaLibraryDataAbility::Delete(const Uri &uri, const DataAbilityPredicates &predicates)
501 {
502 if (!isRdbStoreInitialized || (rdbStore_ == nullptr)) {
503 MEDIA_ERR_LOG("MediaLibraryDataAbility Delete:Rdb Store is not initialized");
504 return DATA_ABILITY_FAIL;
505 }
506
507 if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
508 return DATA_ABILITY_PERMISSION_DENIED;
509 }
510 string uriString = uri.ToString();
511 string strDeleteCondition = predicates.GetWhereClause();
512 if (strDeleteCondition.empty()) {
513 string::size_type pos = uriString.find_last_of('/');
514 CHECK_AND_RETURN_RET_LOG((pos != string::npos) && (pos == MEDIALIBRARY_DATA_URI.length()), DATA_ABILITY_FAIL,
515 "Invalid index position");
516
517 string strRow = uriString.substr(pos + 1);
518 CHECK_AND_RETURN_RET_LOG(MediaLibraryDataAbilityUtils::IsNumber(strRow), DATA_ABILITY_FAIL, "Index not digit");
519
520 strDeleteCondition = MEDIA_DATA_DB_ID + " = " + strRow;
521 uriString = uriString.substr(0, pos);
522 }
523
524 // After removing the index values, check whether URI is correct
525 CHECK_AND_RETURN_RET_LOG(uriString == MEDIALIBRARY_DATA_URI, DATA_ABILITY_FAIL, "Not Data ability Uri");
526
527 vector<string> whereArgs = predicates.GetWhereArgs();
528 int32_t deletedRows = DATA_ABILITY_FAIL;
529 (void)rdbStore_->Delete(deletedRows, MEDIALIBRARY_TABLE, strDeleteCondition, whereArgs);
530
531 return deletedRows;
532 }
QueryBySmartTableType(TableType tabletype,string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore)533 shared_ptr<AbsSharedResultSet> QueryBySmartTableType(TableType tabletype,
534 string strQueryCondition,
535 DataAbilityPredicates predicates,
536 vector<string> columns,
537 std::shared_ptr<NativeRdb::RdbStore> rdbStore)
538 {
539 shared_ptr<AbsSharedResultSet> queryResultSet;
540 if (tabletype == TYPE_SMARTALBUM) {
541 AbsRdbPredicates mediaLibSAAbsPred(SMARTALBUM_TABLE);
542 if (predicates.IsDistinct()) {
543 mediaLibSAAbsPred.Distinct();
544 }
545
546 mediaLibSAAbsPred.SetWhereClause(strQueryCondition);
547 mediaLibSAAbsPred.SetWhereArgs(predicates.GetWhereArgs());
548 mediaLibSAAbsPred.Limit(predicates.GetLimit());
549 mediaLibSAAbsPred.SetOrder(predicates.GetOrder());
550
551 queryResultSet = rdbStore->Query(mediaLibSAAbsPred, columns);
552 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
553 } else if (tabletype == TYPE_SMARTALBUM_MAP) {
554 AbsRdbPredicates mediaLibSAMAbsPred(SMARTALBUM_MAP_TABLE);
555 if (predicates.IsDistinct()) {
556 mediaLibSAMAbsPred.Distinct();
557 }
558
559 mediaLibSAMAbsPred.SetWhereClause(strQueryCondition);
560 mediaLibSAMAbsPred.SetWhereArgs(predicates.GetWhereArgs());
561 mediaLibSAMAbsPred.Limit(predicates.GetLimit());
562 mediaLibSAMAbsPred.SetOrder(predicates.GetOrder());
563
564 queryResultSet = rdbStore->Query(mediaLibSAMAbsPred, columns);
565 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
566 }
567 return queryResultSet;
568 }
569
QueryFile(string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore,string networkId)570 shared_ptr<AbsSharedResultSet> QueryFile(string strQueryCondition,
571 DataAbilityPredicates predicates,
572 vector<string> columns,
573 std::shared_ptr<NativeRdb::RdbStore> rdbStore,
574 string networkId)
575 {
576 shared_ptr<AbsSharedResultSet> queryResultSet;
577 string tableName = MEDIALIBRARY_TABLE;
578 if (!networkId.empty()) {
579 MEDIA_DEBUG_LOG("ObtainDistributedTableName start");
580 StartTrace(BYTRACE_TAG_OHOS, "QueryFile rdbStore->ObtainDistributedTableName");
581 tableName = rdbStore->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE);
582 MEDIA_DEBUG_LOG("tableName in %{public}s", tableName.c_str());
583 FinishTrace(BYTRACE_TAG_OHOS);
584 }
585 AbsRdbPredicates mediaLibAbsPredFile(tableName);
586
587 if (!networkId.empty()) {
588 MEDIA_INFO_LOG("Not empty networkId %{public}s", networkId.c_str());
589 std::vector<string> devices = std::vector<string>();
590 devices.push_back(networkId);
591 mediaLibAbsPredFile.InDevices(devices);
592 }
593 if (predicates.IsDistinct()) {
594 mediaLibAbsPredFile.Distinct();
595 }
596 mediaLibAbsPredFile.SetWhereClause(strQueryCondition);
597 mediaLibAbsPredFile.SetWhereArgs(predicates.GetWhereArgs());
598 mediaLibAbsPredFile.Limit(predicates.GetLimit());
599 mediaLibAbsPredFile.SetOrder(predicates.GetOrder());
600
601 StartTrace(BYTRACE_TAG_OHOS, "QueryFile RdbStore->Query");
602 queryResultSet = rdbStore->Query(mediaLibAbsPredFile, columns);
603 FinishTrace(BYTRACE_TAG_OHOS);
604
605 return queryResultSet;
606 }
607
ObtionCondition(string & strQueryCondition,const vector<string> & whereArgs)608 string ObtionCondition(string &strQueryCondition, const vector<string> &whereArgs)
609 {
610 for (string args : whereArgs) {
611 size_t pos = strQueryCondition.find('?');
612 MEDIA_INFO_LOG("obtionCondition pos = %{public}d", (int)pos);
613 if (pos != string::npos) {
614 MEDIA_INFO_LOG("ObtionCondition before = %{public}s", strQueryCondition.c_str());
615 strQueryCondition.replace(pos, 1, "'" + args + "'");
616 MEDIA_INFO_LOG("ObtionCondition end = %{public}s", strQueryCondition.c_str());
617 }
618 }
619 return strQueryCondition;
620 }
621
QueryAlbum(string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore,string networkId)622 shared_ptr<AbsSharedResultSet> QueryAlbum(string strQueryCondition,
623 DataAbilityPredicates predicates,
624 vector<string> columns,
625 std::shared_ptr<NativeRdb::RdbStore> rdbStore,
626 string networkId)
627 {
628 shared_ptr<AbsSharedResultSet> queryResultSet;
629 if (!networkId.empty()) {
630 string tableName = rdbStore->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE);
631 MEDIA_INFO_LOG("tableName is %{public}s", tableName.c_str());
632 AbsRdbPredicates mediaLibAbsPredAlbum(tableName);
633 if (!strQueryCondition.empty()) {
634 strQueryCondition = ObtionCondition(strQueryCondition, predicates.GetWhereArgs());
635 }
636 string distributedAlbumSql = MediaLibraryDataAbilityUtils::GetDistributedAlbumSql(strQueryCondition, tableName);
637 queryResultSet = rdbStore->QuerySql(distributedAlbumSql);
638 } else {
639 AbsRdbPredicates mediaLibAbsPredAlbum(ABLUM_VIEW_NAME);
640 if (strQueryCondition.empty()) {
641 queryResultSet = rdbStore->QuerySql("SELECT * FROM " + ABLUM_VIEW_NAME);
642 } else {
643 if (predicates.IsDistinct()) {
644 mediaLibAbsPredAlbum.Distinct();
645 }
646 mediaLibAbsPredAlbum.SetWhereClause(strQueryCondition);
647 mediaLibAbsPredAlbum.SetWhereArgs(predicates.GetWhereArgs());
648 mediaLibAbsPredAlbum.Limit(predicates.GetLimit());
649 mediaLibAbsPredAlbum.SetOrder(predicates.GetOrder());
650 queryResultSet = rdbStore->Query(mediaLibAbsPredAlbum, columns);
651 }
652 }
653 return queryResultSet;
654 }
655
QueryDeviceInfo(string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore)656 shared_ptr<AbsSharedResultSet> QueryDeviceInfo(string strQueryCondition,
657 DataAbilityPredicates predicates, vector<string> columns, std::shared_ptr<NativeRdb::RdbStore> rdbStore)
658 {
659 shared_ptr<AbsSharedResultSet> queryResultSet;
660 AbsRdbPredicates deviceAbsRdbPredicates(DEVICE_TABLE);
661 if (predicates.IsDistinct()) {
662 deviceAbsRdbPredicates.Distinct();
663 }
664
665 deviceAbsRdbPredicates.SetWhereClause(strQueryCondition);
666 deviceAbsRdbPredicates.SetWhereArgs(predicates.GetWhereArgs());
667 deviceAbsRdbPredicates.Limit(predicates.GetLimit());
668 deviceAbsRdbPredicates.SetOrder(predicates.GetOrder());
669
670 queryResultSet = rdbStore->Query(deviceAbsRdbPredicates, columns);
671 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query All Device failed");
672 return queryResultSet;
673 }
674
QueryByViewType(TableType tabletype,string strQueryCondition,DataAbilityPredicates predicates,vector<string> columns,std::shared_ptr<NativeRdb::RdbStore> rdbStore)675 shared_ptr<AbsSharedResultSet> QueryByViewType(TableType tabletype,
676 string strQueryCondition,
677 DataAbilityPredicates predicates,
678 vector<string> columns,
679 std::shared_ptr<NativeRdb::RdbStore> rdbStore)
680 {
681 shared_ptr<AbsSharedResultSet> queryResultSet;
682 if (tabletype == TYPE_ASSETSMAP_TABLE) {
683 AbsRdbPredicates mediaLibAbsPredAlbum(ASSETMAP_VIEW_NAME);
684 if (strQueryCondition.empty()) {
685 queryResultSet = rdbStore->QuerySql("SELECT * FROM " + ASSETMAP_VIEW_NAME);
686 } else {
687 if (predicates.IsDistinct()) {
688 mediaLibAbsPredAlbum.Distinct();
689 }
690 mediaLibAbsPredAlbum.SetWhereClause(strQueryCondition);
691 mediaLibAbsPredAlbum.SetWhereArgs(predicates.GetWhereArgs());
692 mediaLibAbsPredAlbum.Limit(predicates.GetLimit());
693 mediaLibAbsPredAlbum.SetOrder(predicates.GetOrder());
694 queryResultSet = rdbStore->Query(mediaLibAbsPredAlbum, columns);
695 }
696 } else if (tabletype == TYPE_SMARTALBUMASSETS_TABLE) {
697 AbsRdbPredicates mediaLibAbsPredAlbum(SMARTABLUMASSETS_VIEW_NAME);
698 if (strQueryCondition.empty()) {
699 queryResultSet = rdbStore->QuerySql("SELECT * FROM " + SMARTABLUMASSETS_VIEW_NAME);
700 } else {
701 if (predicates.IsDistinct()) {
702 mediaLibAbsPredAlbum.Distinct();
703 }
704 mediaLibAbsPredAlbum.SetWhereClause(strQueryCondition);
705 mediaLibAbsPredAlbum.SetWhereArgs(predicates.GetWhereArgs());
706 mediaLibAbsPredAlbum.Limit(predicates.GetLimit());
707 mediaLibAbsPredAlbum.SetOrder(predicates.GetOrder());
708 queryResultSet = rdbStore->Query(mediaLibAbsPredAlbum, columns);
709 }
710 }
711 return queryResultSet;
712 }
SplitKeyValue(const string & keyValue,string & key,string & value)713 void SplitKeyValue(const string& keyValue, string &key, string &value)
714 {
715 string::size_type pos = keyValue.find('=');
716 if (string::npos != pos) {
717 key = keyValue.substr(0, pos);
718 value = keyValue.substr(pos + 1);
719 }
720 }
SplitKeys(const string & query,vector<string> & keys)721 void SplitKeys(const string& query, vector<string>& keys)
722 {
723 string::size_type pos1 = 0;
724 string::size_type pos2 = query.find('&');
725 while (string::npos != pos2) {
726 keys.push_back(query.substr(pos1, pos2-pos1));
727 pos1 = pos2 + 1;
728 pos2 = query.find('&', pos1);
729 }
730 if (pos1 != query.length()) {
731 keys.push_back(query.substr(pos1));
732 }
733 }
ParseThumbnailInfo(string & uriString,vector<int> & space)734 bool ParseThumbnailInfo(string &uriString, vector<int> &space)
735 {
736 string::size_type pos = uriString.find_last_of('?');
737 string queryKeys;
738 if (string::npos == pos) {
739 return false;
740 }
741 vector<string> keyWords = {
742 MEDIA_OPERN_KEYWORD,
743 MEDIA_DATA_DB_WIDTH,
744 MEDIA_DATA_DB_HEIGHT
745 };
746 queryKeys = uriString.substr(pos + 1);
747 uriString = uriString.substr(0, pos);
748 vector<string> vectorKeys;
749 SplitKeys(queryKeys, vectorKeys);
750 if (vectorKeys.size() != keyWords.size()) {
751 MEDIA_ERR_LOG("Parse error keys count %{public}d", (int)vectorKeys.size());
752 return false;
753 }
754 string action;
755 int width = 0;
756 int height = 0;
757 for (uint32_t i = 0; i < vectorKeys.size(); i++) {
758 string subKey, subVal;
759 SplitKeyValue(vectorKeys[i], subKey, subVal);
760 if (subKey.empty()) {
761 MEDIA_ERR_LOG("Parse key error [ %{public}s ]", vectorKeys[i].c_str());
762 return false;
763 }
764 if (subKey == MEDIA_OPERN_KEYWORD) {
765 action = subVal;
766 } else if (subKey == MEDIA_DATA_DB_WIDTH) {
767 if (MediaLibraryDataAbilityUtils::IsNumber(subVal)) {
768 width = stoi(subVal);
769 }
770 } else if (subKey == MEDIA_DATA_DB_HEIGHT) {
771 if (MediaLibraryDataAbilityUtils::IsNumber(subVal)) {
772 height = stoi(subVal);
773 }
774 }
775 }
776 MEDIA_INFO_LOG("ParseThumbnailInfo| action [%{public}s] width %{public}d height %{public}d",
777 action.c_str(), width, height);
778 if (action != MEDIA_DATA_DB_THUMBNAIL || width <= 0 || height <= 0) {
779 MEDIA_ERR_LOG("ParseThumbnailInfo | Error args");
780 return false;
781 }
782 space.push_back(width);
783 space.push_back(height);
784 return true;
785 }
GenThumbnail(shared_ptr<RdbStore> rdb,shared_ptr<MediaLibraryThumbnail> thumbnail,string & rowId,vector<int> space,string & networkId)786 shared_ptr<AbsSharedResultSet> GenThumbnail(shared_ptr<RdbStore> rdb,
787 shared_ptr<MediaLibraryThumbnail> thumbnail,
788 string &rowId, vector<int> space, string &networkId)
789 {
790 shared_ptr<AbsSharedResultSet> queryResultSet;
791 int width = space[0];
792 int height = space[1];
793 string filesTableName = MEDIALIBRARY_TABLE;
794
795 if (!networkId.empty()) {
796 StartTrace(BYTRACE_TAG_OHOS, "rdb->ObtainDistributedTableName");
797 filesTableName = rdb->ObtainDistributedTableName(networkId, MEDIALIBRARY_TABLE);
798 FinishTrace(BYTRACE_TAG_OHOS);
799 }
800
801 MEDIA_INFO_LOG("Get filesTableName [ %{public}s ]", filesTableName.c_str());
802 ThumbRdbOpt opts = {
803 .store = rdb,
804 .table = filesTableName,
805 .row = rowId
806 };
807 Size size = {
808 .width = width,
809 .height = height
810 };
811
812 MEDIA_INFO_LOG("Get thumbnail [ %{public}s ]", opts.row.c_str());
813 StartTrace(BYTRACE_TAG_OHOS, "thumbnail->GetThumbnailKey");
814 queryResultSet = thumbnail->GetThumbnailKey(opts, size);
815 FinishTrace(BYTRACE_TAG_OHOS);
816
817 return queryResultSet;
818 }
DealWithUriString(string & uriString,TableType & tabletype,string & strQueryCondition,string::size_type & pos,string & strRow)819 static void DealWithUriString(string &uriString, TableType &tabletype,
820 string &strQueryCondition, string::size_type &pos, string &strRow)
821 {
822 string type = uriString.substr(pos + 1);
823 MEDIA_INFO_LOG("MediaLibraryDataAbility uriString type = %{public}s", type.c_str());
824 if (type == MEDIA_ALBUMOPRN_QUERYALBUM) {
825 tabletype = TYPE_ALBUM_TABLE;
826 uriString = MEDIALIBRARY_DATA_URI;
827 } else if (uriString == MEDIALIBRARY_DATA_URI + "/"
828 + MEDIA_ALBUMOPRN_QUERYALBUM + "/" + SMARTABLUMASSETS_VIEW_NAME) {
829 tabletype = TYPE_SMARTALBUMASSETS_TABLE;
830 uriString = MEDIALIBRARY_SMARTALBUM_URI;
831 } else if (uriString == MEDIALIBRARY_DATA_URI + "/"
832 + MEDIA_ALBUMOPRN_QUERYALBUM + "/" + ASSETMAP_VIEW_NAME) {
833 tabletype = TYPE_ASSETSMAP_TABLE;
834 uriString = MEDIALIBRARY_SMARTALBUM_URI;
835 } else if (uriString == MEDIALIBRARY_DATA_URI + "/" + MEDIA_DEVICE_QUERYALLDEVICE) {
836 tabletype = TYPE_ALL_DEVICE;
837 uriString = MEDIALIBRARY_DATA_URI;
838 } else if (uriString == MEDIALIBRARY_DATA_URI + "/" + MEDIA_DEVICE_QUERYACTIVEDEVICE) {
839 tabletype = TYPE_ACTIVE_DEVICE;
840 uriString = MEDIALIBRARY_DATA_URI;
841 } else if (strQueryCondition.empty() && pos != string::npos) {
842 strRow = type;
843 uriString = uriString.substr(0, pos);
844 string::size_type posTable = uriString.find_last_of('/');
845 string tableName = uriString.substr(posTable + 1);
846 MEDIA_INFO_LOG("MediaLibraryDataAbility tableName = %{public}s", tableName.c_str());
847 MEDIA_INFO_LOG("MediaLibraryDataAbility strRow = %{public}s", strRow.c_str());
848 if (SMARTALBUM_TABLE.compare(tableName) == 0) {
849 tabletype = TYPE_SMARTALBUM;
850 strQueryCondition = SMARTALBUM_DB_ID + " = " + strRow;
851 } else if (SMARTALBUM_MAP_TABLE.compare(tableName) == 0) {
852 tabletype = TYPE_SMARTALBUM_MAP;
853 strQueryCondition = SMARTALBUMMAP_DB_ALBUM_ID + " = " + strRow;
854 } else {
855 tabletype = TYPE_DATA;
856 strQueryCondition = MEDIA_DATA_DB_ID + " = " + strRow;
857 }
858 }
859 }
Query(const Uri & uri,const vector<string> & columns,const DataAbilityPredicates & predicates)860 shared_ptr<AbsSharedResultSet> MediaLibraryDataAbility::Query(const Uri &uri,
861 const vector<string> &columns,
862 const DataAbilityPredicates &predicates)
863 {
864 StartTrace(BYTRACE_TAG_OHOS, "MediaLibraryDataAbility::Query");
865
866 if ((!isRdbStoreInitialized) || (rdbStore_ == nullptr)) {
867 MEDIA_ERR_LOG("Rdb Store is not initialized");
868 return nullptr;
869 }
870
871 StartTrace(BYTRACE_TAG_OHOS, "CheckClientPermission");
872 if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA)) {
873 return nullptr;
874 }
875 FinishTrace(BYTRACE_TAG_OHOS);
876
877 shared_ptr<AbsSharedResultSet> queryResultSet;
878 TableType tabletype = TYPE_DATA;
879 string strRow, uriString = uri.ToString(), strQueryCondition = predicates.GetWhereClause();
880
881 if (!CheckWhereClause(strQueryCondition)) {
882 MEDIA_ERR_LOG("illegal query whereClause input %{public}s", strQueryCondition.c_str());
883 return nullptr;
884 }
885
886 vector<int> space;
887 bool thumbnailQuery = ParseThumbnailInfo(uriString, space);
888 string networkId = MediaLibraryDataAbilityUtils::GetNetworkIdFromUri(uriString);
889 string::size_type pos = uriString.find_last_of('/');
890 string type = uriString.substr(pos + 1);
891 MEDIA_DEBUG_LOG("uriString = %{public}s, type = %{public}s, thumbnailQuery %{public}d, Rdb Verison %{public}d",
892 uriString.c_str(), type.c_str(), thumbnailQuery, MEDIA_RDB_VERSION);
893 DealWithUriString(uriString, tabletype, strQueryCondition, pos, strRow);
894
895 if (!networkId.empty() && (tabletype != TYPE_ASSETSMAP_TABLE) && (tabletype != TYPE_SMARTALBUMASSETS_TABLE)) {
896 StartTrace(BYTRACE_TAG_OHOS, "QuerySync");
897 auto ret = QuerySync();
898 FinishTrace(BYTRACE_TAG_OHOS);
899 MEDIA_INFO_LOG("MediaLibraryDataAbility QuerySync result = %{public}d", ret);
900 }
901
902 if (thumbnailQuery) {
903 StartTrace(BYTRACE_TAG_OHOS, "GenThumbnail");
904 queryResultSet = GenThumbnail(rdbStore_, mediaThumbnail_, strRow, space, networkId);
905 FinishTrace(BYTRACE_TAG_OHOS);
906 } else if (tabletype == TYPE_SMARTALBUM || tabletype == TYPE_SMARTALBUM_MAP) {
907 queryResultSet = QueryBySmartTableType(tabletype, strQueryCondition, predicates, columns, rdbStore_);
908 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
909 } else if (tabletype == TYPE_ASSETSMAP_TABLE || tabletype == TYPE_SMARTALBUMASSETS_TABLE) {
910 queryResultSet = QueryByViewType(tabletype, strQueryCondition, predicates, columns, rdbStore_);
911 } else if (tabletype == TYPE_ALL_DEVICE || tabletype == TYPE_ACTIVE_DEVICE) {
912 queryResultSet = QueryDeviceInfo(strQueryCondition, predicates, columns, rdbStore_);
913 } else if (tabletype == TYPE_ALBUM_TABLE) {
914 queryResultSet = QueryAlbum(strQueryCondition, predicates, columns, rdbStore_, networkId);
915 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
916 } else {
917 StartTrace(BYTRACE_TAG_OHOS, "QueryFile");
918 queryResultSet = QueryFile(strQueryCondition, predicates, columns, rdbStore_, networkId);
919 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, nullptr, "Query functionality failed");
920 FinishTrace(BYTRACE_TAG_OHOS);
921 }
922
923 FinishTrace(BYTRACE_TAG_OHOS);
924
925 return queryResultSet;
926 }
927
Update(const Uri & uri,const ValuesBucket & value,const DataAbilityPredicates & predicates)928 int32_t MediaLibraryDataAbility::Update(const Uri &uri, const ValuesBucket &value,
929 const DataAbilityPredicates &predicates)
930 {
931 MEDIA_INFO_LOG("Update");
932 if ((!isRdbStoreInitialized) || (rdbStore_ == nullptr) || (value.IsEmpty())) {
933 MEDIA_ERR_LOG("MediaLibraryDataAbility Update:Input parameter is invalid ");
934 return DATA_ABILITY_FAIL;
935 }
936 if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
937 return DATA_ABILITY_PERMISSION_DENIED;
938 }
939 MediaLibraryFileOperations fileOprn;
940 int32_t changedRows = DATA_ABILITY_FAIL;
941 string uriString = uri.ToString();
942 vector<string> devices = vector<string>();
943 MEDIA_INFO_LOG("Update uriString = %{public}s", uriString.c_str());
944 string strUpdateCondition = predicates.GetWhereClause();
945 if (strUpdateCondition.empty()) {
946 string::size_type pos = uriString.find_last_of('/');
947 CHECK_AND_RETURN_RET_LOG((pos != string::npos) && (pos == MEDIALIBRARY_DATA_URI.length()), DATA_ABILITY_FAIL,
948 "Invalid index position");
949
950 string strRow = uriString.substr(pos + 1);
951 CHECK_AND_RETURN_RET_LOG(MediaLibraryDataAbilityUtils::IsNumber(strRow), DATA_ABILITY_FAIL, "Index not digit");
952
953 uriString = uriString.substr(0, pos);
954 strUpdateCondition = MEDIA_DATA_DB_ID + " = " + strRow;
955 }
956 // After removing the index values, check whether URI is correct
957
958 vector<string> whereArgs = predicates.GetWhereArgs();
959 if (uriString.find(MEDIA_SMARTALBUMOPRN) != string::npos) {
960 (void)rdbStore_->Update(changedRows, SMARTALBUM_TABLE, value, strUpdateCondition, whereArgs);
961 } else if (uriString.find(MEDIA_SMARTALBUMMAPOPRN) != string::npos) {
962 (void)rdbStore_->Update(changedRows, SMARTALBUM_MAP_TABLE, value, strUpdateCondition, whereArgs);
963 } else {
964 if (uriString == MEDIALIBRARY_DATA_URI + "/" + Media::MEDIA_FILEOPRN
965 + "/" + Media::MEDIA_FILEOPRN_MODIFYASSET) {
966 int result = fileOprn.HandleFileOperation(MEDIA_FILEOPRN_MODIFYASSET, value, rdbStore_, mediaThumbnail_);
967 if (result < 0) {
968 return result;
969 }
970 }
971 (void)rdbStore_->Update(changedRows, MEDIALIBRARY_TABLE, value, strUpdateCondition, whereArgs);
972 }
973 if (changedRows >= 0) {
974 MediaLibrarySyncTable syncTable;
975 syncTable.SyncPushTable(rdbStore_, bundleName_, MEDIALIBRARY_TABLE, devices);
976 }
977 return changedRows;
978 }
979
BatchInsert(const Uri & uri,const vector<ValuesBucket> & values)980 int32_t MediaLibraryDataAbility::BatchInsert(const Uri &uri, const vector<ValuesBucket> &values)
981 {
982 string uriString = uri.ToString();
983 if ((!isRdbStoreInitialized) || (rdbStore_ == nullptr) || (uriString != MEDIALIBRARY_DATA_URI)) {
984 MEDIA_ERR_LOG("MediaLibraryDataAbility BatchInsert: Input parameter is invalid");
985 return DATA_ABILITY_FAIL;
986 }
987 int32_t rowCount = 0;
988 for (auto it = values.begin(); it != values.end(); it++) {
989 if (Insert(uri, *it) >= 0) {
990 rowCount++;
991 }
992 }
993
994 return rowCount;
995 }
996
ScanFile(const ValuesBucket & values,const shared_ptr<RdbStore> & rdbStore1)997 void MediaLibraryDataAbility::ScanFile(const ValuesBucket &values, const shared_ptr<RdbStore> &rdbStore1)
998 {
999 if (scannerClient_ == nullptr) {
1000 scannerClient_ = MediaScannerHelperFactory::CreateScannerHelper();
1001 }
1002
1003 if (scannerClient_ != nullptr) {
1004 string actualUri;
1005 ValueObject valueObject;
1006
1007 if (values.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
1008 valueObject.GetString(actualUri);
1009 }
1010
1011 string id = MediaLibraryDataAbilityUtils::GetIdFromUri(actualUri);
1012 string srcPath = MediaLibraryDataAbilityUtils::GetPathFromDb(id, rdbStore1);
1013 if (!srcPath.empty()) {
1014 std::shared_ptr<ScanFileCallback> scanFileCb = make_shared<ScanFileCallback>();
1015 CHECK_AND_RETURN_LOG(scanFileCb != nullptr, "Failed to create scan file callback object");
1016 auto ret = scannerClient_->ScanFile(srcPath, scanFileCb);
1017 CHECK_AND_RETURN_LOG(ret == 0, "Failed to initiate scan request");
1018 }
1019 }
1020 }
1021 /**
1022 * @brief
1023 * @param uri
1024 * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
1025 * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
1026 * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data,
1027 * or "rwt" for read and write access that truncates any existing file.
1028 * /
1029 * @return int32_t
1030 */
OpenFile(const Uri & uri,const std::string & mode)1031 int32_t MediaLibraryDataAbility::OpenFile(const Uri &uri, const std::string &mode)
1032 {
1033 string uriString = uri.ToString();
1034 shared_ptr<FileAsset> fileAsset = MediaLibraryDataAbilityUtils::GetFileAssetFromDb(uriString, rdbStore_);
1035 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, DATA_ABILITY_FAIL, "Failed to obtain path from Database");
1036 bool isWriteMode = MediaLibraryDataAbilityUtils::checkOpenMode(mode);
1037 if (isWriteMode) {
1038 if (MediaLibraryDataAbilityUtils::checkFilePending(fileAsset)) {
1039 MEDIA_ERR_LOG("MediaLibraryDataAbility OpenFile: File is pending");
1040 return DATA_ABILITY_HAS_OPENED_FAIL;
1041 }
1042 }
1043 if (mode == MEDIA_FILEMODE_READONLY) {
1044 if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA)) {
1045 return DATA_ABILITY_PERMISSION_DENIED;
1046 }
1047 } else if (mode == MEDIA_FILEMODE_WRITEONLY || mode == MEDIA_FILEMODE_WRITETRUNCATE ||
1048 mode == MEDIA_FILEMODE_WRITEAPPEND) {
1049 if (!CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
1050 return DATA_ABILITY_PERMISSION_DENIED;
1051 }
1052 } else if (mode == MEDIA_FILEMODE_READWRITETRUNCATE || mode == MEDIA_FILEMODE_READWRITE) {
1053 if (!CheckClientPermission(PERMISSION_NAME_READ_MEDIA) ||
1054 !CheckClientPermission(PERMISSION_NAME_WRITE_MEDIA)) {
1055 return DATA_ABILITY_PERMISSION_DENIED;
1056 }
1057 }
1058 string path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
1059 int32_t fd = fileAsset->OpenAsset(path, mode);
1060 if (fd < 0) {
1061 MEDIA_ERR_LOG("open file fd %{public}d, errno %{public}d", fd, errno);
1062 return DATA_ABILITY_HAS_FD_ERROR;
1063 }
1064 if (isWriteMode && fd > 0) {
1065 int32_t errorCode = MediaLibraryDataAbilityUtils::setFilePending(uriString, true, rdbStore_);
1066 if (errorCode == DATA_ABILITY_FAIL) {
1067 fileAsset->CloseAsset(fd);
1068 MEDIA_ERR_LOG("MediaLibraryDataAbility OpenFile: Set file to pending DB error");
1069 return DATA_ABILITY_HAS_DB_ERROR;
1070 }
1071 }
1072 MEDIA_INFO_LOG("MediaLibraryDataAbility OpenFile: Success");
1073 return fd;
1074 }
1075
InitDeviceData()1076 void MediaLibraryDataAbility::InitDeviceData()
1077 {
1078 if (rdbStore_ == nullptr) {
1079 MEDIA_ERR_LOG("MediaLibraryDataAbility InitDeviceData rdbStore is null");
1080 return;
1081 }
1082 std::string extra = "";
1083 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
1084 deviceInitCallback_ = std::make_shared<MediaLibraryInitCallback>();
1085 if (deviceInitCallback_ == nullptr) {
1086 MEDIA_ERR_LOG("MediaLibraryDataAbility MediaLibraryInitCallback failed!");
1087 return;
1088 }
1089 deviceManager.InitDeviceManager(bundleName_, deviceInitCallback_);
1090
1091 MEDIA_DEBUG_LOG("Distribute StartTrace:InitDeviceRdbStoreTrace");
1092 StartTrace(BYTRACE_TAG_OHOS, "InitDeviceRdbStoreTrace", -1);
1093 if (!MediaLibraryDevice::GetInstance()->InitDeviceRdbStore(rdbStore_, bundleName_)) {
1094 MEDIA_ERR_LOG("MediaLibraryDataAbility InitDeviceData failed!");
1095 return;
1096 }
1097 FinishTrace(BYTRACE_TAG_OHOS);
1098 MEDIA_DEBUG_LOG("Distribute FinishTrace:InitDeviceRdbStoreTrace");
1099
1100 deviceStateCallback_ = std::make_shared<MediaLibraryDeviceStateCallback>(rdbStore_, bundleName_);
1101 if (deviceStateCallback_ == nullptr) {
1102 MEDIA_ERR_LOG("MediaLibraryDataAbility MediaLibraryDeviceStateCallback failed!");
1103 return;
1104 }
1105
1106 if (deviceManager.RegisterDevStateCallback(bundleName_, extra, deviceStateCallback_) != 0) {
1107 deviceStateCallback_ = nullptr;
1108 MEDIA_ERR_LOG("MediaLibraryDataAbility RegisterDevStateCallback failed!");
1109 return;
1110 }
1111 MEDIA_INFO_LOG("MediaLibraryDataAbility InitDeviceData OUT");
1112 }
1113
SubscribeRdbStoreObserver()1114 bool MediaLibraryDataAbility::SubscribeRdbStoreObserver()
1115 {
1116 if (rdbStore_ == nullptr) {
1117 MEDIA_ERR_LOG("MediaLibraryDataAbility SubscribeRdbStoreObserver rdbStore is null");
1118 return false;
1119 }
1120 rdbStoreObs_ = std::make_shared<MediaLibraryRdbStoreObserver>(bundleName_);
1121 if (rdbStoreObs_ == nullptr) {
1122 return false;
1123 }
1124
1125 DistributedRdb::SubscribeOption option;
1126 option.mode = DistributedRdb::SubscribeMode::REMOTE;
1127 bool ret = rdbStore_->Subscribe(option, rdbStoreObs_.get());
1128 MEDIA_INFO_LOG("MediaLibraryDataAbility Subscribe ret = %d", ret);
1129
1130 return ret;
1131 }
1132
UnSubscribeRdbStoreObserver()1133 bool MediaLibraryDataAbility::UnSubscribeRdbStoreObserver()
1134 {
1135 if (rdbStore_ == nullptr) {
1136 MEDIA_ERR_LOG("MediaLibraryDataAbility UnSubscribeRdbStoreObserver rdbStore is null");
1137 return false;
1138 }
1139
1140 DistributedRdb::SubscribeOption option;
1141 option.mode = DistributedRdb::SubscribeMode::REMOTE;
1142 bool ret = rdbStore_->UnSubscribe(option, rdbStoreObs_.get());
1143 MEDIA_INFO_LOG("MediaLibraryDataAbility UnSubscribe ret = %d", ret);
1144 if (ret) {
1145 rdbStoreObs_ = nullptr;
1146 }
1147
1148 return ret;
1149 }
1150
QuerySync(const std::string & deviceId,const std::string & tableName)1151 bool MediaLibraryDataAbility::QuerySync(const std::string &deviceId, const std::string &tableName)
1152 {
1153 if (deviceId.empty() || tableName.empty()) {
1154 return false;
1155 }
1156
1157 OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
1158 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
1159 auto ret = deviceManager.GetLocalDeviceInfo(bundleName_, deviceInfo);
1160 if (ret != ERR_OK) {
1161 MEDIA_ERR_LOG("MediaLibraryDataAbility QuerySync Failed to get local device info.");
1162 return false;
1163 }
1164
1165 if (deviceId == std::string(deviceInfo.deviceId)) {
1166 return true;
1167 }
1168
1169 int32_t syncStatus = DEVICE_SYNCSTATUSING;
1170 auto result = MediaLibraryDevice::GetInstance()->GetDevicieSyncStatus(deviceId, syncStatus, bundleName_);
1171 if (result && syncStatus == DEVICE_SYNCSTATUS_COMPLETE) {
1172 return true;
1173 }
1174
1175 std::vector<std::string> devices = { deviceId };
1176 MediaLibrarySyncTable syncTable;
1177 return syncTable.SyncPullTable(rdbStore_, bundleName_, tableName, devices);
1178 }
1179
QuerySync()1180 bool MediaLibraryDataAbility::QuerySync()
1181 {
1182 std::string strQueryCondition = DEVICE_DB_SYNC_STATUS + "=" + std::to_string(DEVICE_SYNCSTATUSING) +
1183 " AND " + DEVICE_DB_DATE_MODIFIED + "=0";
1184
1185 std::vector<std::string> columns;
1186 std::vector<std::string> devices;
1187 shared_ptr<AbsSharedResultSet> queryResultSet;
1188 AbsRdbPredicates deviceAbsRdbPredicates(DEVICE_TABLE);
1189 deviceAbsRdbPredicates.SetWhereClause(strQueryCondition);
1190
1191 queryResultSet = rdbStore_->Query(deviceAbsRdbPredicates, columns);
1192 if (queryResultSet == nullptr) {
1193 return false;
1194 }
1195
1196 if (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
1197 int32_t columnIndexId;
1198 std::string deviceId;
1199 queryResultSet->GetColumnIndex(DEVICE_DB_DEVICEID, columnIndexId);
1200 queryResultSet->GetString(columnIndexId, deviceId);
1201
1202 if (!deviceId.empty()) {
1203 devices.push_back(deviceId);
1204 }
1205 }
1206
1207 if (devices.empty()) {
1208 return true;
1209 }
1210
1211 MediaLibrarySyncTable syncTable;
1212 return syncTable.SyncPullAllTableByDeviceId(rdbStore_, bundleName_, devices);
1213 }
1214
CheckFileNameValid(const ValuesBucket & value)1215 bool MediaLibraryDataAbility::CheckFileNameValid(const ValuesBucket &value)
1216 {
1217 ValueObject valueObject;
1218 string displayName("");
1219 if (!value.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
1220 return false;
1221 }
1222 valueObject.GetString(displayName);
1223
1224 if (displayName.empty()) {
1225 return false;
1226 }
1227
1228 if (displayName.at(0) == '.') {
1229 std::string bundleName = GetClientBundleName();
1230 if (IsSameTextStr(displayName, ".nofile") && IsSameTextStr(bundleName, "fms_service")) {
1231 return true;
1232 }
1233 return false;
1234 }
1235 return true;
1236 }
1237
GetSysBundleManager()1238 sptr<AppExecFwk::IBundleMgr> MediaLibraryDataAbility::GetSysBundleManager()
1239 {
1240 if (bundleMgr_ == nullptr) {
1241 std::lock_guard<std::mutex> lock(bundleMgrMutex);
1242 if (bundleMgr_ == nullptr) {
1243 auto saMgr = OHOS::DelayedSingleton<SaMgrClient>::GetInstance();
1244 if (saMgr == nullptr) {
1245 MEDIA_ERR_LOG("failed to get SaMgrClient::GetInstance");
1246 return nullptr;
1247 }
1248 auto bundleObj = saMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
1249 if (bundleObj == nullptr) {
1250 MEDIA_ERR_LOG("failed to get GetSystemAbility");
1251 return nullptr;
1252 }
1253 auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
1254 if (bundleMgr == nullptr) {
1255 MEDIA_ERR_LOG("failed to iface_cast");
1256 return nullptr;
1257 }
1258 bundleMgr_ = bundleMgr;
1259 }
1260 }
1261 return bundleMgr_;
1262 }
1263
GetClientBundle(int uid)1264 std::string MediaLibraryDataAbility::GetClientBundle(int uid)
1265 {
1266 auto bms = GetSysBundleManager();
1267 std::string bundleName = "";
1268 if (bms == nullptr) {
1269 MEDIA_INFO_LOG("GetClientBundleName bms failed");
1270 return bundleName;
1271 }
1272 auto result = bms->GetBundleNameForUid(uid, bundleName);
1273 MEDIA_INFO_LOG("uid %{public}d bundleName is %{public}s ", uid, bundleName.c_str());
1274 if (!result) {
1275 MEDIA_ERR_LOG("GetBundleNameForUid fail");
1276 return "";
1277 }
1278 return bundleName;
1279 }
1280
GetClientBundleName()1281 std::string MediaLibraryDataAbility::GetClientBundleName()
1282 {
1283 int uid = IPCSkeleton::GetCallingUid();
1284 return GetClientBundle(uid);
1285 }
1286
CheckClientPermission(const std::string & permissionStr)1287 bool MediaLibraryDataAbility::CheckClientPermission(const std::string& permissionStr)
1288 {
1289 int uid = IPCSkeleton::GetCallingUid();
1290 if (UID_FREE_CHECK.find(uid) != UID_FREE_CHECK.end()) {
1291 MEDIA_INFO_LOG("CheckClientPermission: Pass the uid white list");
1292 return true;
1293 }
1294
1295 std::string bundleName = GetClientBundle(uid);
1296 MEDIA_INFO_LOG("CheckClientPermission: bundle name: %{public}s", bundleName.c_str());
1297 if (BUNDLE_FREE_CHECK.find(bundleName) != BUNDLE_FREE_CHECK.end()) {
1298 MEDIA_INFO_LOG("CheckClientPermission: Pass the bundle name white list");
1299 return true;
1300 }
1301
1302 auto bundleMgr = GetSysBundleManager();
1303 if ((bundleMgr != nullptr) && bundleMgr->CheckIsSystemAppByUid(uid) &&
1304 (SYSTEM_BUNDLE_FREE_CHECK.find(bundleName) != SYSTEM_BUNDLE_FREE_CHECK.end())) {
1305 MEDIA_INFO_LOG("CheckClientPermission: Pass the system bundle name white list");
1306 return true;
1307 }
1308
1309 Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
1310 int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller,
1311 permissionStr);
1312 if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
1313 MEDIA_ERR_LOG("MediaLibraryDataAbility Query: Have no media permission");
1314 return false;
1315 }
1316 return true;
1317 }
1318
InitialiseKvStore()1319 void MediaLibraryDataAbility::InitialiseKvStore()
1320 {
1321 MEDIA_INFO_LOG("MediaLibraryDataAbility::InitialiseKvStore");
1322 if (kvStorePtr_ != nullptr) {
1323 return;
1324 }
1325
1326 Options options = {
1327 .createIfMissing = true,
1328 .encrypt = false,
1329 .autoSync = false,
1330 .kvStoreType = KvStoreType::SINGLE_VERSION
1331 };
1332
1333 Status status = dataManager_.GetSingleKvStore(options, KVSTORE_APPID, KVSTORE_STOREID, kvStorePtr_);
1334 if (status != Status::SUCCESS || kvStorePtr_ == nullptr) {
1335 MEDIA_INFO_LOG("MediaLibraryDataAbility::InitialiseKvStore failed %{public}d", status);
1336 }
1337 }
1338
OnScanFinished(const int32_t status,const std::string & uri,const std::string & path)1339 void ScanFileCallback::OnScanFinished(const int32_t status, const std::string &uri, const std::string &path) {}
1340
OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1341 void MediaLibraryDeviceStateCallback::OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1342 {
1343 MediaLibraryDevice::GetInstance()->OnDeviceOnline(deviceInfo, bundleName_);
1344
1345 MediaLibrarySyncTable syncTable;
1346 std::string deviceId = deviceInfo.deviceId;
1347 std::vector<std::string> devices = { deviceId };
1348 syncTable.SyncPullAllTableByDeviceId(rdbStore_, bundleName_, devices);
1349 }
1350
OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1351 void MediaLibraryDeviceStateCallback::OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1352 {
1353 MediaLibraryDevice::GetInstance()->OnDeviceOffline(deviceInfo, bundleName_);
1354 }
1355
OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1356 void MediaLibraryDeviceStateCallback::OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1357 {
1358 MediaLibraryDevice::GetInstance()->OnDeviceChanged(deviceInfo);
1359 }
1360
OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)1361 void MediaLibraryDeviceStateCallback::OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
1362 {
1363 MediaLibraryDevice::GetInstance()->OnDeviceReady(deviceInfo);
1364 }
1365
OnRemoteDied()1366 void MediaLibraryInitCallback::OnRemoteDied()
1367 {
1368 MEDIA_INFO_LOG("MediaLibraryInitCallback OnRemoteDied call");
1369 }
1370
MediaLibraryRdbStoreObserver(std::string & bundleName)1371 MediaLibraryRdbStoreObserver::MediaLibraryRdbStoreObserver(std::string &bundleName)
1372 {
1373 bundleName_ = bundleName;
1374 isNotifyDeviceChange_ = false;
1375
1376 if (timer_ == nullptr) {
1377 timer_ = std::make_unique<OHOS::Utils::Timer>(bundleName_);
1378 timerId_ = timer_->Register(std::bind(&MediaLibraryRdbStoreObserver::NotifyDeviceChange, this),
1379 NOTIFY_TIME_INTERVAL);
1380 timer_->Setup();
1381 }
1382 }
1383
~MediaLibraryRdbStoreObserver()1384 MediaLibraryRdbStoreObserver::~MediaLibraryRdbStoreObserver()
1385 {
1386 if (timer_ != nullptr) {
1387 timer_->Shutdown();
1388 timer_->Unregister(timerId_);
1389 timer_ = nullptr;
1390 }
1391 }
1392
OnChange(const std::vector<std::string> & devices)1393 void MediaLibraryRdbStoreObserver::OnChange(const std::vector<std::string>& devices)
1394 {
1395 MEDIA_INFO_LOG("MediaLibraryRdbStoreObserver OnChange call");
1396 if (devices.empty() || bundleName_.empty()) {
1397 return;
1398 }
1399 MediaLibraryDevice::GetInstance()->NotifyRemoteFileChange();
1400 for (auto &deviceId : devices) {
1401 MediaLibraryDevice::GetInstance()->UpdateDevicieSyncStatus(deviceId, DEVICE_SYNCSTATUS_COMPLETE, bundleName_);
1402 isNotifyDeviceChange_ = true;
1403 }
1404 }
1405
NotifyDeviceChange()1406 void MediaLibraryRdbStoreObserver::NotifyDeviceChange()
1407 {
1408 if (isNotifyDeviceChange_) {
1409 MediaLibraryDevice::GetInstance()->NotifyDeviceChange();
1410 isNotifyDeviceChange_ = false;
1411 }
1412 }
1413 } // namespace Media
1414 } // namespace OHOS
1415