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 #define MLOG_TAG "FileOperation"
16
17 #include "medialibrary_file_operations.h"
18
19 #include "datashare_predicates.h"
20 #include "datashare_values_bucket.h"
21 #include "file_asset.h"
22 #include "hitrace_meter.h"
23 #include "media_file_utils.h"
24 #include "media_log.h"
25 #include "medialibrary_data_manager_utils.h"
26 #include "medialibrary_db_const.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_notify.h"
29 #include "medialibrary_object_utils.h"
30 #include "medialibrary_smartalbum_map_operations.h"
31 #include "medialibrary_tracer.h"
32 #include "medialibrary_unistore_manager.h"
33 #include "native_album_asset.h"
34 #include "rdb_utils.h"
35
36 using namespace std;
37 using namespace OHOS::NativeRdb;
38 using namespace OHOS::DataShare;
39 using namespace OHOS::RdbDataShareAdapter;
40
41 namespace OHOS {
42 namespace Media {
43 using ChangeType = AAFwk::ChangeInfo::ChangeType;
44
HandleFileOperation(MediaLibraryCommand & cmd)45 int32_t MediaLibraryFileOperations::HandleFileOperation(MediaLibraryCommand &cmd)
46 {
47 int32_t errCode = E_FAIL;
48 auto values = cmd.GetValueBucket();
49 string actualUri;
50
51 ValueObject valueObject;
52 if (values.GetObject(MEDIA_DATA_DB_URI, valueObject)) {
53 valueObject.GetString(actualUri);
54 }
55
56 // only support CloseAsset when networkId is not empty
57 string networkId = MediaLibraryDataManagerUtils::GetNetworkIdFromUri(actualUri);
58 if (!networkId.empty() && cmd.GetOprnType() != OperationType::CLOSE) {
59 return E_PERMISSION_DENIED;
60 }
61
62 switch (cmd.GetOprnType()) {
63 case OperationType::CREATE:
64 errCode = CreateFileOperation(cmd);
65 break;
66 case OperationType::CLOSE:
67 errCode = CloseFileOperation(cmd);
68 break;
69 case OperationType::GETCAPACITY:
70 errCode = GetAlbumCapacityOperation(cmd);
71 break;
72 case OperationType::COPY:
73 errCode = CopyFileOperation(cmd);
74 break;
75 default:
76 MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
77 break;
78 }
79 return errCode;
80 }
81
CreateFileOperation(MediaLibraryCommand & cmd)82 int32_t MediaLibraryFileOperations::CreateFileOperation(MediaLibraryCommand &cmd)
83 {
84 return MediaLibraryObjectUtils::CreateFileObj(cmd);
85 }
86
CloseFileOperation(MediaLibraryCommand & cmd)87 int32_t MediaLibraryFileOperations::CloseFileOperation(MediaLibraryCommand &cmd)
88 {
89 return MediaLibraryObjectUtils::CloseFile(cmd);
90 }
91
QueryFavFiles(MediaLibraryCommand & cmd)92 shared_ptr<NativeRdb::ResultSet> MediaLibraryFileOperations::QueryFavFiles(MediaLibraryCommand &cmd)
93 {
94 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_IS_FAV, "1");
95 cmd.GetAbsRdbPredicates()->And()->NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, std::to_string(MEDIA_TYPE_ALBUM));
96
97 return MediaLibraryObjectUtils::QueryWithCondition(cmd, {});
98 }
99
QueryTrashFiles(MediaLibraryCommand & cmd)100 shared_ptr<NativeRdb::ResultSet> MediaLibraryFileOperations::QueryTrashFiles(MediaLibraryCommand &cmd)
101 {
102 cmd.GetAbsRdbPredicates()
103 ->GreaterThan(MEDIA_DATA_DB_DATE_TRASHED, std::to_string(NOT_TRASHED))
104 ->And()
105 ->NotEqualTo(MEDIA_DATA_DB_MEDIA_TYPE, std::to_string(MEDIA_TYPE_ALBUM));
106
107 return MediaLibraryObjectUtils::QueryWithCondition(cmd, {});
108 }
109
GetAlbumCapacityOperation(MediaLibraryCommand & cmd)110 int32_t MediaLibraryFileOperations::GetAlbumCapacityOperation(MediaLibraryCommand &cmd)
111 {
112 int32_t errorCode = E_FAIL;
113 shared_ptr<NativeRdb::ResultSet> resultSet = nullptr;
114
115 auto values = cmd.GetValueBucket();
116 ValueObject valueObject;
117 int32_t isFavourite = 0;
118 bool isTrash = false;
119 if (values.GetObject(MEDIA_DATA_DB_IS_FAV, valueObject)) {
120 valueObject.GetInt(isFavourite);
121 }
122 if (values.GetObject(MEDIA_DATA_DB_IS_TRASH, valueObject)) {
123 valueObject.GetBool(isTrash);
124 }
125
126 if (isFavourite != 0) {
127 resultSet = QueryFavFiles(cmd);
128 } else if (isTrash) {
129 resultSet = QueryTrashFiles(cmd);
130 }
131
132 if (resultSet != nullptr) {
133 resultSet->GetRowCount(errorCode);
134 MEDIA_INFO_LOG("GetRowCount %{private}d", errorCode);
135 }
136
137 return errorCode;
138 }
139
ModifyFileOperation(MediaLibraryCommand & cmd)140 int32_t MediaLibraryFileOperations::ModifyFileOperation(MediaLibraryCommand &cmd)
141 {
142 string strFileId = cmd.GetOprnFileId();
143 if (strFileId.empty()) {
144 MEDIA_ERR_LOG("MediaLibraryFileOperations::ModifyFileOperation Get id from uri or valuesBucket failed!");
145 return E_INVALID_FILEID;
146 }
147
148 string srcPath = MediaLibraryObjectUtils::GetPathByIdFromDb(strFileId);
149 if (srcPath.empty()) {
150 MEDIA_ERR_LOG("MediaLibraryFileOperations::ModifyFileOperation Get path of id %{private}s from database file!",
151 strFileId.c_str());
152 return E_INVALID_FILEID;
153 }
154
155 string dstFileName;
156 string dstReFilePath;
157 auto values = cmd.GetValueBucket();
158 ValueObject valueObject;
159 if (values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
160 valueObject.GetString(dstFileName);
161 }
162 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
163 valueObject.GetString(dstReFilePath);
164 }
165 string dstFilePath = ROOT_MEDIA_DIR + dstReFilePath + dstFileName;
166
167 if (srcPath.compare(dstFilePath) == 0) {
168 return E_SAME_PATH;
169 }
170 return MediaLibraryObjectUtils::RenameFileObj(cmd, srcPath, dstFilePath);
171 }
172
173 constexpr bool START_PENDING = false;
SolvePendingInQuery(AbsRdbPredicates * predicates)174 static void SolvePendingInQuery(AbsRdbPredicates* predicates)
175 {
176 string whereClause = predicates->GetWhereClause();
177 size_t groupByPoint = whereClause.rfind("GROUP BY");
178 string groupBy;
179 if (groupByPoint != string::npos) {
180 groupBy = whereClause.substr(groupByPoint);
181 whereClause = whereClause.substr(0, groupByPoint);
182 }
183
184 predicates->SetWhereClause(whereClause);
185 predicates->EqualTo(MEDIA_DATA_DB_TIME_PENDING, "0");
186 if (!groupBy.empty()) {
187 predicates->SetWhereClause(predicates->GetWhereClause() + groupBy);
188 }
189 }
190
191 #ifdef MEDIALIBRARY_COMPATIBILITY
PhotosCompatColumns()192 static const vector<string> &PhotosCompatColumns()
193 {
194 /*
195 * Caution: Columns MUST KEEP SAME ORDER for sqlite UNION operation in:
196 * o PHOTOS_COMPAT_COLUMNS
197 * o AUDIOS_COMPAT_COLUMNS
198 * o FILES_COMPAT_COLUMNS
199 */
200 static const vector<string> PHOTOS_COMPAT_COLUMNS = {
201 MEDIA_DATA_DB_ID,
202 MEDIA_DATA_DB_FILE_PATH,
203 COMPAT_COLUMN_URI,
204 MEDIA_DATA_DB_MIME_TYPE,
205 MEDIA_DATA_DB_MEDIA_TYPE,
206 MEDIA_DATA_DB_NAME,
207 MEDIA_DATA_DB_TITLE,
208 MEDIA_DATA_DB_RELATIVE_PATH,
209 MEDIA_DATA_DB_PARENT_ID,
210 MEDIA_DATA_DB_SIZE,
211 MEDIA_DATA_DB_DATE_ADDED,
212 MEDIA_DATA_DB_DATE_MODIFIED,
213 MEDIA_DATA_DB_DATE_TAKEN,
214 COMPAT_COLUMN_ARTIST,
215 COMPAT_COLUMN_AUDIO_ALBUM,
216 MEDIA_DATA_DB_WIDTH,
217 MEDIA_DATA_DB_HEIGHT,
218 MEDIA_DATA_DB_ORIENTATION,
219 MEDIA_DATA_DB_DURATION,
220 COMPAT_COLUMN_BUCKET_ID,
221 COMPAT_COLUMN_BUCKET_NAME,
222 COMPAT_COLUMN_IS_TRASH,
223 MEDIA_DATA_DB_IS_FAV,
224 MEDIA_DATA_DB_DATE_TRASHED,
225
226 MediaColumn::MEDIA_HIDDEN,
227 PhotoColumn::PHOTO_SYNC_STATUS,
228 PhotoColumn::PHOTO_SUBTYPE,
229 };
230 return PHOTOS_COMPAT_COLUMNS;
231 }
232
AudiosCompatColumns()233 static const vector<string> &AudiosCompatColumns()
234 {
235 /*
236 * Caution: Columns MUST KEEP SAME ORDER for sqlite UNION operation in:
237 * o PHOTOS_COMPAT_COLUMNS
238 * o AUDIOS_COMPAT_COLUMNS
239 * o FILES_COMPAT_COLUMNS
240 */
241 static const vector<string> AUDIOS_COMPAT_COLUMNS = {
242 MEDIA_DATA_DB_ID,
243 MEDIA_DATA_DB_FILE_PATH,
244 COMPAT_COLUMN_URI,
245 MEDIA_DATA_DB_MIME_TYPE,
246 MEDIA_DATA_DB_MEDIA_TYPE,
247 MEDIA_DATA_DB_NAME,
248 MEDIA_DATA_DB_TITLE,
249 MEDIA_DATA_DB_RELATIVE_PATH,
250 MEDIA_DATA_DB_PARENT_ID,
251 MEDIA_DATA_DB_SIZE,
252 MEDIA_DATA_DB_DATE_ADDED,
253 MEDIA_DATA_DB_DATE_MODIFIED,
254 MEDIA_DATA_DB_DATE_TAKEN,
255 MEDIA_DATA_DB_ARTIST,
256 MEDIA_DATA_DB_AUDIO_ALBUM,
257 COMPAT_COLUMN_WIDTH,
258 COMPAT_COLUMN_HEIGHT,
259 COMPAT_COLUMN_ORIENTATION,
260 MEDIA_DATA_DB_DURATION,
261 COMPAT_COLUMN_BUCKET_ID,
262 COMPAT_COLUMN_BUCKET_NAME,
263 COMPAT_COLUMN_IS_TRASH,
264 MEDIA_DATA_DB_IS_FAV,
265 MEDIA_DATA_DB_DATE_TRASHED,
266
267 DEFAULT_INT_COLUMN_AS + MediaColumn::MEDIA_HIDDEN,
268 DEFAULT_INT_COLUMN_AS + PhotoColumn::PHOTO_SYNC_STATUS,
269 DEFAULT_INT_COLUMN_AS + PhotoColumn::PHOTO_SUBTYPE,
270 };
271 return AUDIOS_COMPAT_COLUMNS;
272 }
273
FilesCompatColumns()274 static const vector<string> &FilesCompatColumns()
275 {
276 /*
277 * Caution: KEEP SAME ORDER for sqlite UNION operation in columns below:
278 * o PHOTOS_COMPAT_COLUMNS
279 * o AUDIOS_COMPAT_COLUMNS
280 * o FILES_COMPAT_COLUMNS
281 */
282 static const vector<string> FILES_COMPAT_COLUMNS = {
283 MEDIA_DATA_DB_ID,
284 MEDIA_DATA_DB_FILE_PATH,
285 MEDIA_DATA_DB_URI,
286 MEDIA_DATA_DB_MIME_TYPE,
287 MEDIA_DATA_DB_MEDIA_TYPE,
288 MEDIA_DATA_DB_NAME,
289 MEDIA_DATA_DB_TITLE,
290 MEDIA_DATA_DB_RELATIVE_PATH,
291 MEDIA_DATA_DB_PARENT_ID,
292 MEDIA_DATA_DB_SIZE,
293 MEDIA_DATA_DB_DATE_ADDED,
294 MEDIA_DATA_DB_DATE_MODIFIED,
295 MEDIA_DATA_DB_DATE_TAKEN,
296 MEDIA_DATA_DB_ARTIST,
297 COMPAT_COLUMN_AUDIO_ALBUM,
298 MEDIA_DATA_DB_WIDTH,
299 MEDIA_DATA_DB_HEIGHT,
300 MEDIA_DATA_DB_ORIENTATION,
301 MEDIA_DATA_DB_DURATION,
302 MEDIA_DATA_DB_BUCKET_ID,
303 MEDIA_DATA_DB_BUCKET_NAME,
304 MEDIA_DATA_DB_IS_TRASH,
305 MEDIA_DATA_DB_IS_FAV,
306 MEDIA_DATA_DB_DATE_TRASHED,
307
308 DEFAULT_INT_COLUMN_AS + MediaColumn::MEDIA_HIDDEN,
309 PhotoColumn::PHOTO_SYNC_STATUS,
310 DEFAULT_INT_COLUMN_AS + PhotoColumn::PHOTO_SUBTYPE,
311 };
312
313 return FILES_COMPAT_COLUMNS;
314 }
315
BuildQueryColumns(const vector<string> & columns,string & sql)316 static void BuildQueryColumns(const vector<string> &columns, string &sql)
317 {
318 for (const auto &col : columns) {
319 sql += col + ',';
320 }
321 sql.pop_back(); // Remove last ','
322 }
323
ReplaceAlbumName(const string & arg,string & argInstead)324 static void ReplaceAlbumName(const string &arg, string &argInstead)
325 {
326 if (arg == CAMERA_ALBUM_NAME) {
327 argInstead = to_string(static_cast<int32_t>(PhotoSubType::CAMERA));
328 } else if (arg == SCREEN_SHOT_ALBUM_NAME || arg == SCREEN_RECORD_ALBUM_NAME) {
329 argInstead = to_string(static_cast<int32_t>(PhotoSubType::SCREENSHOT));
330 } else {
331 argInstead = arg;
332 }
333 }
334
ReplaceId(const string & fileId,string & idInstead,const string & tableName)335 static void ReplaceId(const string &fileId, string &idInstead, const string &tableName)
336 {
337 if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
338 return;
339 }
340 int32_t id = stoi(fileId);
341 idInstead = to_string(MediaFileUtils::GetRealIdByTable(id, tableName));
342 }
343
ReplaceSelectionAndArgsInQuery(string & selection,vector<string> & selectionArgs,const string & tableName,const string & key,const string & keyInstead="")344 static void ReplaceSelectionAndArgsInQuery(string &selection, vector<string> &selectionArgs,
345 const string &tableName, const string &key, const string &keyInstead = "")
346 {
347 if (selection.empty()) {
348 return;
349 }
350
351 for (size_t pos = 0; pos != string::npos;) {
352 pos = selection.find(key, pos);
353 if (pos == string::npos) {
354 break;
355 }
356 if (!keyInstead.empty()) {
357 selection.replace(pos, key.length(), keyInstead);
358 }
359 size_t argPos = selection.find('?', pos);
360 if (argPos == string::npos) {
361 break;
362 }
363 size_t argIndex = 0;
364 for (size_t i = 0; i < argPos; i++) {
365 if (selection[i] == '?') {
366 argIndex++;
367 }
368 }
369 if (argIndex > selectionArgs.size() - 1) {
370 MEDIA_INFO_LOG("SelectionArgs size is not valid, selection format maybe incorrect: %{private}s",
371 selection.c_str());
372 break;
373 }
374 const string &arg = selectionArgs[argIndex];
375 string argInstead = arg;
376 if (key == MEDIA_DATA_DB_BUCKET_NAME) {
377 ReplaceAlbumName(arg, argInstead);
378 } else if (key == MEDIA_DATA_DB_ID) {
379 ReplaceId(arg, argInstead, tableName);
380 }
381 selectionArgs[argIndex] = argInstead;
382 pos = argPos + 1;
383 }
384 }
385
BuildCompatQuerySql(MediaLibraryCommand & cmd,const string table,const vector<string> & columns,vector<string> & selectionArgs,string & sql)386 static void BuildCompatQuerySql(MediaLibraryCommand &cmd, const string table, const vector<string> &columns,
387 vector<string> &selectionArgs, string &sql)
388 {
389 sql += "SELECT ";
390 BuildQueryColumns(columns, sql);
391 sql += " FROM " + table;
392
393 string whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
394 vector<string> whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
395 if (table == PhotoColumn::PHOTOS_TABLE) {
396 ReplaceSelectionAndArgsInQuery(whereClause, whereArgs, table, MEDIA_DATA_DB_BUCKET_NAME,
397 PhotoColumn::PHOTO_SUBTYPE);
398 }
399 ReplaceSelectionAndArgsInQuery(whereClause, whereArgs, table, MEDIA_DATA_DB_ID);
400
401 if (!whereClause.empty()) {
402 sql += " WHERE " + whereClause;
403 }
404
405 if (!whereArgs.empty()) {
406 selectionArgs.insert(selectionArgs.end(), whereArgs.begin(), whereArgs.end());
407 }
408 }
409
RemoveWhereSuffix(MediaLibraryCommand & cmd,const string & key)410 static string RemoveWhereSuffix(MediaLibraryCommand &cmd, const string &key)
411 {
412 string suffix;
413 string whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
414 size_t keyPos = MediaFileUtils::FindIgnoreCase(whereClause, key);
415 if (keyPos != string::npos) {
416 suffix = whereClause.substr(keyPos);
417 whereClause = whereClause.substr(0, keyPos);
418 }
419 cmd.GetAbsRdbPredicates()->SetWhereClause(whereClause);
420 return suffix;
421 }
422
BuildQueryFileSql(MediaLibraryCommand & cmd,vector<string> & selectionArgs,string & sql)423 static void BuildQueryFileSql(MediaLibraryCommand &cmd, vector<string> &selectionArgs, string &sql)
424 {
425 string groupBy = RemoveWhereSuffix(cmd, " GROUP BY ");
426 string having = RemoveWhereSuffix(cmd, " HAVING ");
427 string orderBy = RemoveWhereSuffix(cmd, " ORDER BY ");
428 string limit = RemoveWhereSuffix(cmd, " LIMIT ");
429
430 sql = "SELECT ";
431 if (!groupBy.empty()) {
432 sql += "count(*),";
433 }
434 BuildQueryColumns(FILE_ASSET_COLUMNS, sql);
435
436 sql += " FROM (";
437 BuildCompatQuerySql(cmd, PhotoColumn::PHOTOS_TABLE, PhotosCompatColumns(), selectionArgs, sql);
438 sql += " UNION ";
439 BuildCompatQuerySql(cmd, AudioColumn::AUDIOS_TABLE, AudiosCompatColumns(), selectionArgs, sql);
440 sql += " UNION ";
441 BuildCompatQuerySql(cmd, MEDIALIBRARY_TABLE, FilesCompatColumns(), selectionArgs, sql);
442 sql += ") ";
443
444 if (!groupBy.empty()) {
445 sql += groupBy;
446 }
447 if (!having.empty()) {
448 sql += having;
449 }
450
451 const string &order = cmd.GetAbsRdbPredicates()->GetOrder();
452 if ((!order.empty()) && (!orderBy.empty())) {
453 MEDIA_WARN_LOG("ORDER BY found both in whereClause and predicates, use the predicates one");
454 sql += " ORDER BY " + order;
455 } else if (!order.empty()) {
456 sql += " ORDER BY " + order;
457 } else if (!orderBy.empty()) {
458 sql += orderBy;
459 }
460
461 if (!limit.empty()) {
462 sql += limit;
463 }
464 }
465
CampatQueryDebug(const string & sql,const vector<string> & selectionArgs,const shared_ptr<MediaLibraryUnistore> & store)466 static void CampatQueryDebug(const string &sql, const vector<string> &selectionArgs,
467 const shared_ptr<MediaLibraryUnistore> &store)
468 {
469 constexpr int32_t printMax = 512;
470 for (size_t pos = 0; pos < sql.size(); pos += printMax) {
471 MEDIA_DEBUG_LOG("Quering file sql: %{public}s", sql.substr(pos, printMax).c_str());
472 }
473 for (const auto &arg : selectionArgs) {
474 MEDIA_DEBUG_LOG("Quering file, arg: %{public}s", arg.c_str());
475 }
476 auto resultSet = store->QuerySql(sql, selectionArgs);
477 if (resultSet == nullptr) {
478 MEDIA_ERR_LOG("Failed to query file!");
479 return;
480 }
481 int32_t count = -1;
482 int32_t err = resultSet->GetRowCount(count);
483 if (err != E_OK) {
484 MEDIA_ERR_LOG("Failed to get count, err: %{public}d", err);
485 return;
486 }
487 MEDIA_DEBUG_LOG("Quering file, count: %{public}d", count);
488 }
489 #endif
490
QueryFileOperation(MediaLibraryCommand & cmd,const vector<string> & columns)491 shared_ptr<NativeRdb::ResultSet> MediaLibraryFileOperations::QueryFileOperation(
492 MediaLibraryCommand &cmd, const vector<string> &columns)
493 {
494 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
495 if (uniStore == nullptr) {
496 MEDIA_ERR_LOG("uniStore is nullptr");
497 return nullptr;
498 }
499
500 string fileId = cmd.GetOprnFileId();
501 if (cmd.GetAbsRdbPredicates()->GetWhereClause().empty() && !fileId.empty()) {
502 cmd.GetAbsRdbPredicates()->EqualTo(MEDIA_DATA_DB_ID, fileId);
503 }
504
505 if (START_PENDING) {
506 SolvePendingInQuery(cmd.GetAbsRdbPredicates());
507 }
508 string networkId = cmd.GetOprnDevice();
509 if (!networkId.empty()) {
510 std::vector<string> devices;
511 devices.push_back(networkId);
512 cmd.GetAbsRdbPredicates()->InDevices(devices);
513 }
514 MediaLibraryTracer tracer;
515 tracer.Start("QueryFile RdbStore->Query");
516
517 #ifdef MEDIALIBRARY_COMPATIBILITY
518 string sql;
519 vector<string> selectionArgs;
520 BuildQueryFileSql(cmd, selectionArgs, sql);
521 CampatQueryDebug(sql, selectionArgs, uniStore);
522 return uniStore->QuerySql(sql, selectionArgs);
523 #else
524 return uniStore->Query(cmd, columns);
525 #endif
526 }
527
CopyFileOperation(MediaLibraryCommand & cmd)528 int32_t MediaLibraryFileOperations::CopyFileOperation(MediaLibraryCommand &cmd)
529 {
530 auto values = cmd.GetValueBucket();
531 auto assetId = cmd.GetOprnFileId();
532 ValueObject valueObject;
533 string relativePath;
534 if (values.GetObject(MEDIA_DATA_DB_RELATIVE_PATH, valueObject)) {
535 valueObject.GetString(relativePath);
536 }
537 Uri srcUri(MEDIALIBRARY_DATA_URI + "/" + assetId);
538 string srcUriString = srcUri.ToString();
539 shared_ptr<FileAsset> srcFileAsset = MediaLibraryObjectUtils::GetFileAssetFromUri(srcUriString);
540 if (srcFileAsset == nullptr) {
541 return E_INVALID_URI;
542 }
543 if (srcFileAsset->GetMediaType() == MEDIA_TYPE_ALBUM) {
544 return MediaLibraryObjectUtils::CopyDir(srcFileAsset, relativePath);
545 } else {
546 return MediaLibraryObjectUtils::CopyAsset(srcFileAsset, relativePath);
547 }
548 }
549 } // namespace Media
550 } // namespace OHOS
551