• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include "medialibrary_asset_operations.h"
17 
18 #include <algorithm>
19 #include <dirent.h>
20 #include <memory>
21 #include <mutex>
22 #include <sstream>
23 #include <sys/stat.h>
24 
25 #include "cloud_media_asset_manager.h"
26 #include "dfx_utils.h"
27 #include "directory_ex.h"
28 #include "file_asset.h"
29 #include "media_app_uri_permission_column.h"
30 #include "media_column.h"
31 #include "media_exif.h"
32 #include "media_file_utils.h"
33 #include "media_file_uri.h"
34 #include "media_log.h"
35 #include "media_scanner_manager.h"
36 #include "media_unique_number_column.h"
37 #include "medialibrary_album_operations.h"
38 #include "medialibrary_async_worker.h"
39 #include "medialibrary_audio_operations.h"
40 #include "medialibrary_bundle_manager.h"
41 #include "medialibrary_command.h"
42 #include "medialibrary_common_utils.h"
43 #include "medialibrary_data_manager.h"
44 #include "medialibrary_data_manager_utils.h"
45 #include "medialibrary_db_const.h"
46 #include "medialibrary_errno.h"
47 #include "medialibrary_inotify.h"
48 #ifdef META_RECOVERY_SUPPORT
49 #include "medialibrary_meta_recovery.h"
50 #endif
51 #include "medialibrary_notify.h"
52 #include "medialibrary_photo_operations.h"
53 #include "medialibrary_rdb_transaction.h"
54 #include "medialibrary_rdb_utils.h"
55 #include "medialibrary_rdbstore.h"
56 #include "medialibrary_tracer.h"
57 #include "medialibrary_type_const.h"
58 #include "medialibrary_unistore_manager.h"
59 #include "medialibrary_urisensitive_operations.h"
60 #include "media_privacy_manager.h"
61 #include "mimetype_utils.h"
62 #include "multistages_capture_manager.h"
63 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
64 #include "enhancement_manager.h"
65 #endif
66 #include "permission_utils.h"
67 #include "photo_album_column.h"
68 #include "photo_file_utils.h"
69 #include "rdb_errno.h"
70 #include "rdb_predicates.h"
71 #include "rdb_store.h"
72 #include "rdb_utils.h"
73 #include "result_set_utils.h"
74 #include "thumbnail_service.h"
75 #include "uri_permission_manager_client.h"
76 #include "userfile_manager_types.h"
77 #include "value_object.h"
78 #include "values_bucket.h"
79 #include "medialibrary_formmap_operations.h"
80 #include "medialibrary_vision_operations.h"
81 #include "dfx_manager.h"
82 #include "dfx_const.h"
83 #include "moving_photo_file_utils.h"
84 #include "userfilemgr_uri.h"
85 #include "medialibrary_album_fusion_utils.h"
86 #include "unique_fd.h"
87 
88 using namespace std;
89 using namespace OHOS::NativeRdb;
90 
91 namespace OHOS {
92 namespace Media {
93 mutex g_uniqueNumberLock;
94 
95 const string DEFAULT_IMAGE_NAME = "IMG_";
96 const string DEFAULT_VIDEO_NAME = "VID_";
97 const string DEFAULT_AUDIO_NAME = "AUD_";
98 constexpr int32_t NO_DESENSITIZE = 3;
99 const string PHOTO_ALBUM_URI_PREFIX = "file://media/PhotoAlbum/";
100 constexpr int32_t UNKNOWN_VALUE = -1;
101 constexpr int32_t LOCAL_PHOTO_POSITION = 1;
102 constexpr int32_t BOTH_LOCAL_CLOUD_PHOTO_POSITION = 3;
103 constexpr int32_t MAX_PROCESS_NUM = 200;
104 constexpr int64_t INVALID_SIZE = 0;
105 const std::string SET_DISPLAY_NAME_KEY = "set_displayName";
106 const std::string CAN_FALLBACK = "can_fallback";
107 const std::string OLD_DISPLAY_NAME = "old_displayName";
108 
109 struct DeletedFilesParams {
110     vector<string> ids;
111     vector<string> paths;
112     vector<string> dateTakens;
113     vector<int32_t> subTypes;
114     vector<int32_t> isTemps;
115 };
116 
HandleInsertOperation(MediaLibraryCommand & cmd)117 int32_t MediaLibraryAssetOperations::HandleInsertOperation(MediaLibraryCommand &cmd)
118 {
119     int errCode = E_ERR;
120     switch (cmd.GetOprnType()) {
121         case OperationType::CREATE:
122             errCode = CreateOperation(cmd);
123             break;
124         case OperationType::CLOSE:
125             errCode = CloseOperation(cmd);
126             break;
127         case OperationType::COMMIT_EDIT:
128             errCode = MediaLibraryPhotoOperations::CommitEditInsert(cmd);
129             if (errCode == E_SUCCESS) {
130                 MediaLibraryVisionOperations::EditCommitOperation(cmd);
131             }
132             break;
133         case OperationType::REVERT_EDIT:
134             errCode = MediaLibraryPhotoOperations::RevertToOrigin(cmd);
135             if (errCode == E_SUCCESS) {
136                 MediaLibraryVisionOperations::EditCommitOperation(cmd);
137             }
138             break;
139         case OperationType::SUBMIT_CACHE:
140             errCode = MediaLibraryPhotoOperations::SubmitCache(cmd);
141             break;
142         case OperationType::CUSTOM_RESTORE:
143             errCode = MediaLibraryPhotoOperations::ProcessCustomRestore(cmd);
144             break;
145         case OperationType::CUSTOM_RESTORE_CANCEL:
146             errCode = MediaLibraryPhotoOperations::CancelCustomRestore(cmd);
147             break;
148         case OperationType::ADD_FILTERS:
149             errCode = MediaLibraryPhotoOperations::AddFilters(cmd);
150             break;
151         case OperationType::SCAN_WITHOUT_ALBUM_UPDATE:
152             errCode = MediaLibraryPhotoOperations::ScanFileWithoutAlbumUpdate(cmd);
153             break;
154         case OperationType::FINISH_REQUEST_PICTURE:
155             errCode = MediaLibraryPhotoOperations::FinishRequestPicture(cmd);
156             break;
157         case OperationType::CLONE_ASSET:
158             errCode = MediaLibraryPhotoOperations::CloneSingleAsset(cmd);
159             break;
160         default:
161             MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
162             break;
163     }
164     return errCode;
165 }
166 
CreateOperation(MediaLibraryCommand & cmd)167 int32_t MediaLibraryAssetOperations::CreateOperation(MediaLibraryCommand &cmd)
168 {
169     // CreateAsset specify type
170     switch (cmd.GetOprnObject()) {
171         case OperationObject::FILESYSTEM_PHOTO:
172         case OperationObject::PTP_OPERATION:
173             return MediaLibraryPhotoOperations::Create(cmd);
174         case OperationObject::FILESYSTEM_AUDIO:
175             return MediaLibraryAudioOperations::Create(cmd);
176         case OperationObject::FILESYSTEM_ASSET:
177             MEDIA_ERR_LOG("create asset by FileSysetm_Asset is deperated");
178             return E_INVALID_VALUES;
179         default:
180             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
181             return E_INVALID_VALUES;
182     }
183 }
184 
DeleteOperation(MediaLibraryCommand & cmd)185 int32_t MediaLibraryAssetOperations::DeleteOperation(MediaLibraryCommand &cmd)
186 {
187     // delete Asset specify type
188     switch (cmd.GetOprnObject()) {
189         case OperationObject::FILESYSTEM_PHOTO:
190             return MediaLibraryPhotoOperations::Delete(cmd);
191         case OperationObject::FILESYSTEM_AUDIO:
192             return MediaLibraryAudioOperations::Delete(cmd);
193         case OperationObject::FILESYSTEM_ASSET:
194             MEDIA_ERR_LOG("delete asset by FILESYSTEM_ASSET is deperated");
195             return E_INVALID_VALUES;
196         default:
197             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
198             return E_INVALID_VALUES;
199     }
200 }
201 
QueryOperation(MediaLibraryCommand & cmd,const vector<string> & columns)202 shared_ptr<NativeRdb::ResultSet> MediaLibraryAssetOperations::QueryOperation(
203     MediaLibraryCommand &cmd, const vector<string> &columns)
204 {
205     // query asset specify type
206     switch (cmd.GetOprnObject()) {
207         case OperationObject::FILESYSTEM_PHOTO:
208         case OperationObject::EDIT_DATA_EXISTS:
209             return MediaLibraryPhotoOperations::Query(cmd, columns);
210         case OperationObject::FILESYSTEM_AUDIO:
211             return MediaLibraryAudioOperations::Query(cmd, columns);
212         case OperationObject::FILESYSTEM_ASSET:
213             MEDIA_ERR_LOG("api9 operation is not finished");
214             return nullptr;
215         case OperationObject::PAH_MOVING_PHOTO:
216             return MediaLibraryPhotoOperations::ScanMovingPhoto(cmd, columns);
217         default:
218             MEDIA_ERR_LOG("error operation objec: %{public}d", cmd.GetOprnObject());
219             return nullptr;
220     }
221 }
222 
UpdateOperation(MediaLibraryCommand & cmd)223 int32_t MediaLibraryAssetOperations::UpdateOperation(MediaLibraryCommand &cmd)
224 {
225     if (!AssetInputParamVerification::CheckParamForUpdate(cmd)) {
226         return E_INVALID_VALUES;
227     }
228 
229     switch (cmd.GetOprnObject()) {
230         case OperationObject::PAH_PHOTO:
231         case OperationObject::PAH_VIDEO:
232         case OperationObject::FILESYSTEM_PHOTO:
233         case OperationObject::PTP_OPERATION:
234             return MediaLibraryPhotoOperations::Update(cmd);
235         case OperationObject::FILESYSTEM_AUDIO:
236             return MediaLibraryAudioOperations::Update(cmd);
237         case OperationObject::FILESYSTEM_ASSET:
238             MEDIA_ERR_LOG("create asset by FILESYSTEM_ASSET is deperated");
239             return E_INVALID_VALUES;
240         default:
241             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
242             return E_INVALID_VALUES;
243     }
244 }
245 
OpenOperation(MediaLibraryCommand & cmd,const string & mode)246 int32_t MediaLibraryAssetOperations::OpenOperation(MediaLibraryCommand &cmd, const string &mode)
247 {
248     MediaLibraryTracer tracer;
249     tracer.Start("MediaLibraryAssetOperations::OpenOperation");
250 
251     // Open specify type
252     switch (cmd.GetOprnObject()) {
253         case OperationObject::FILESYSTEM_PHOTO:
254         case OperationObject::PTP_OPERATION:
255             return MediaLibraryPhotoOperations::Open(cmd, mode);
256         case OperationObject::FILESYSTEM_AUDIO:
257             return MediaLibraryAudioOperations::Open(cmd, mode);
258         case OperationObject::HIGHLIGHT_COVER:
259             return MediaLibraryAssetOperations::OpenHighlightCover(cmd, mode);
260         case OperationObject::HIGHLIGHT_URI:
261             return MediaLibraryAssetOperations::OpenHighlightVideo(cmd, mode);
262         case OperationObject::FILESYSTEM_ASSET:
263             MEDIA_ERR_LOG("open by FILESYSTEM_ASSET is deperated");
264             return E_INVALID_VALUES;
265         default:
266             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
267             return E_INVALID_VALUES;
268     }
269 }
270 
CloseOperation(MediaLibraryCommand & cmd)271 int32_t MediaLibraryAssetOperations::CloseOperation(MediaLibraryCommand &cmd)
272 {
273     // Close specify type
274     switch (cmd.GetOprnObject()) {
275         case OperationObject::FILESYSTEM_PHOTO:
276         case OperationObject::PTP_OPERATION:
277             return MediaLibraryPhotoOperations::Close(cmd);
278         case OperationObject::FILESYSTEM_AUDIO:
279             return MediaLibraryAudioOperations::Close(cmd);
280         case OperationObject::FILESYSTEM_ASSET:
281             MEDIA_ERR_LOG("close by FILESYSTEM_ASSET is deperated");
282             return E_INVALID_VALUES;
283         default:
284             MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
285             return E_INVALID_VALUES;
286     }
287 }
288 
DropAllTables(const shared_ptr<MediaLibraryRdbStore> rdbStore)289 static int32_t DropAllTables(const shared_ptr<MediaLibraryRdbStore> rdbStore)
290 {
291     string dropSqlRowName = "drop_table_and_view_sql";
292     string queryDropSql =
293         "SELECT 'DROP ' || type || ' IF EXISTS ' || name || ';' as " + dropSqlRowName +
294         " FROM sqlite_master" +
295         " WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%';";
296     auto dropSqlsResultSet = rdbStore->QuerySql(queryDropSql);
297     CHECK_AND_RETURN_RET_LOG(dropSqlsResultSet != nullptr, E_HAS_DB_ERROR, "query Drop Sql failed");
298 
299     vector<string> dropSqlsVec;
300     while (dropSqlsResultSet->GoToNextRow() == NativeRdb::E_OK) {
301         int32_t columnIndex = 0;
302         if (dropSqlsResultSet->GetColumnIndex(dropSqlRowName, columnIndex) != NativeRdb::E_OK) {
303             MEDIA_ERR_LOG("Get drop_table_and_view_sql column failed");
304             return E_HAS_DB_ERROR;
305         }
306         string sql;
307         if (dropSqlsResultSet->GetString(columnIndex, sql) != NativeRdb::E_OK) {
308             MEDIA_ERR_LOG("Get drop_table_and_view_sql sql failed");
309             return E_HAS_DB_ERROR;
310         }
311         if (!sql.empty()) {
312             dropSqlsVec.push_back(sql);
313         }
314     }
315 
316     for (const auto &dropSql : dropSqlsVec) {
317         rdbStore->ExecuteSql(dropSql);
318     }
319     return E_OK;
320 }
321 
DeleteToolOperation(MediaLibraryCommand & cmd)322 int32_t MediaLibraryAssetOperations::DeleteToolOperation(MediaLibraryCommand &cmd)
323 {
324     auto valuesBucket = cmd.GetValueBucket();
325     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
326     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Can not get rdb store");
327     int32_t errCode = DropAllTables(rdbStore);
328     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Drop table failed, errCode=%{public}d", errCode);
329     errCode = rdbStore->DataCallBackOnCreate();
330     UriSensitiveOperations::DeleteAllSensitiveAsync();
331     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "DataCallBackOnCreate failed, errCode=%{public}d", errCode);
332 
333     MediaLibraryRdbStore::ResetAnalysisTables();
334     MediaLibraryRdbStore::ResetSearchTables();
335     const static vector<string> DELETE_DIR_LIST = {
336         ROOT_MEDIA_DIR + PHOTO_BUCKET,
337         ROOT_MEDIA_DIR + AUDIO_BUCKET,
338         ROOT_MEDIA_DIR + CAMERA_DIR_VALUES,
339         ROOT_MEDIA_DIR + VIDEO_DIR_VALUES,
340         ROOT_MEDIA_DIR + PIC_DIR_VALUES,
341         ROOT_MEDIA_DIR + AUDIO_DIR_VALUES,
342         ROOT_MEDIA_DIR + ".thumbs",
343         ROOT_MEDIA_DIR + ".editData"
344     };
345 
346     for (const string &dir : DELETE_DIR_LIST) {
347         if (!MediaFileUtils::DeleteDir(dir)) {
348             MEDIA_ERR_LOG("Delete dir %{public}s failed", dir.c_str());
349             continue;
350         }
351         if (!MediaFileUtils::CreateDirectory(dir)) {
352             MEDIA_ERR_LOG("Create dir %{public}s failed", dir.c_str());
353         };
354     }
355 
356     string photoThumbsPath = ROOT_MEDIA_DIR + ".thumbs/Photo";
357     CHECK_AND_PRINT_LOG(MediaFileUtils::CreateDirectory(photoThumbsPath),
358         "Create dir %{public}s failed", photoThumbsPath.c_str());
359     return E_OK;
360 }
361 
CheckOprnObject(OperationObject object)362 static bool CheckOprnObject(OperationObject object)
363 {
364     const set<OperationObject> validOprnObjectet = {
365         OperationObject::FILESYSTEM_PHOTO,
366         OperationObject::FILESYSTEM_AUDIO
367     };
368     if (validOprnObjectet.find(object) == validOprnObjectet.end()) {
369         MEDIA_ERR_LOG("input OperationObject %{public}d error!", object);
370         return false;
371     }
372     return true;
373 }
374 
GetOprnObjectByMediaType(int32_t type)375 static OperationObject GetOprnObjectByMediaType(int32_t type)
376 {
377     switch (type) {
378         case MediaType::MEDIA_TYPE_IMAGE:
379         case MediaType::MEDIA_TYPE_VIDEO: {
380             return OperationObject::FILESYSTEM_PHOTO;
381         }
382         case MediaType::MEDIA_TYPE_AUDIO: {
383             return OperationObject::FILESYSTEM_AUDIO;
384         }
385         case MediaType::MEDIA_TYPE_FILE: {
386             return OperationObject::FILESYSTEM_ASSET;
387         }
388         default: {
389             return OperationObject::UNKNOWN_OBJECT;
390         }
391     }
392 }
393 
FetchFileAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)394 static shared_ptr<FileAsset> FetchFileAssetFromResultSet(
395     const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
396 {
397     int32_t count = 0;
398     int32_t currentRowIndex = 0;
399     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
400     CHECK_AND_RETURN_RET_LOG(
401         resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr, "Cannot get row count of resultset");
402     CHECK_AND_RETURN_RET_LOG(
403         resultSet->GetRowIndex(currentRowIndex) == NativeRdb::E_OK, nullptr, "Cannot get row index of resultset");
404     CHECK_AND_RETURN_RET_LOG(currentRowIndex >= 0 && currentRowIndex < count, nullptr, "Invalid row index");
405 
406     auto fileAsset = make_shared<FileAsset>();
407     auto &map = fileAsset->GetMemberMap();
408     for (const auto &column : columns) {
409         int32_t columnIndex = 0;
410         CHECK_AND_RETURN_RET_LOG(resultSet->GetColumnIndex(column, columnIndex) == NativeRdb::E_OK,
411             nullptr, "Can not get column %{private}s index", column.c_str());
412         CHECK_AND_RETURN_RET_LOG(FILEASSET_MEMBER_MAP.find(column) != FILEASSET_MEMBER_MAP.end(), nullptr,
413             "Can not find column %{private}s from member map", column.c_str());
414         switch (FILEASSET_MEMBER_MAP.at(column)) {
415             case MEMBER_TYPE_INT32: {
416                 int32_t value = 0;
417                 CHECK_AND_RETURN_RET_LOG(resultSet->GetInt(columnIndex, value) == NativeRdb::E_OK, nullptr,
418                     "Can not get int value from column %{private}s", column.c_str());
419                 map[column] = value;
420                 break;
421             }
422             case MEMBER_TYPE_INT64: {
423                 int64_t value = 0;
424                 CHECK_AND_RETURN_RET_LOG(resultSet->GetLong(columnIndex, value) == NativeRdb::E_OK, nullptr,
425                     "Can not get long value from column %{private}s", column.c_str());
426                 map[column] = value;
427                 break;
428             }
429             case MEMBER_TYPE_STRING: {
430                 string value;
431                 CHECK_AND_RETURN_RET_LOG(resultSet->GetString(columnIndex, value) == NativeRdb::E_OK, nullptr,
432                     "Can not get string value from column %{private}s", column.c_str());
433                 map[column] = value;
434                 break;
435             }
436             case MEMBER_TYPE_DOUBLE: {
437                 double value;
438                 CHECK_AND_RETURN_RET_LOG(resultSet->GetDouble(columnIndex, value) == NativeRdb::E_OK, nullptr,
439                     "Can not get double value from column %{private}s", column.c_str());
440                 map[column] = value;
441                 break;
442             }
443         }
444     }
445     return fileAsset;
446 }
447 
GetAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)448 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetAssetFromResultSet(
449     const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
450 {
451     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
452     int32_t count = 0;
453     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr,
454         "Cannot get row count of resultset");
455     CHECK_AND_RETURN_RET_LOG(count == 1, nullptr, "ResultSet count is %{public}d, not 1", count);
456     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "Cannot go to first row");
457     return FetchFileAssetFromResultSet(resultSet, columns);
458 }
459 
GetAssetVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns,vector<shared_ptr<FileAsset>> & fileAssetVector)460 static int32_t GetAssetVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
461     const vector<string> &columns, vector<shared_ptr<FileAsset>> &fileAssetVector)
462 {
463     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "resultSet is nullptr");
464     int32_t count = 0;
465     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
466         "Cannot get row count of resultset");
467     CHECK_AND_RETURN_RET_LOG(count > 0, E_HAS_DB_ERROR, "ResultSet count is %{public}d", count);
468 
469     fileAssetVector.reserve(count);
470     for (int32_t i = 0; i < count; i++) {
471         CHECK_AND_RETURN_RET_LOG(
472             resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
473         auto fileAsset = FetchFileAssetFromResultSet(resultSet, columns);
474         CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Failed to fetch fileAsset from resultSet");
475         fileAssetVector.push_back(fileAsset);
476     }
477     return E_OK;
478 }
479 
GetAlbumVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns,vector<shared_ptr<PhotoAlbum>> & PhotoAlbumVector)480 static int32_t GetAlbumVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
481     const vector<string> &columns, vector<shared_ptr<PhotoAlbum>> &PhotoAlbumVector)
482 {
483     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "resultSet is nullptr");
484     int32_t count = 0;
485     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
486         "Cannot get row count of resultset");
487     CHECK_AND_RETURN_RET_LOG(count > 0, E_HAS_DB_ERROR, "ResultSet count is %{public}d", count);
488 
489     PhotoAlbumVector.reserve(count);
490     for (int32_t i = 0; i < count; i++) {
491         CHECK_AND_RETURN_RET_LOG(
492             resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
493 
494         PhotoAlbumVector.push_back(make_shared<PhotoAlbum>());
495         PhotoAlbumVector.back()->SetPhotoAlbumType(
496             static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet)));
497         PhotoAlbumVector.back()->SetPhotoAlbumSubType(
498             static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet)));
499         PhotoAlbumVector.back()->SetAlbumName(GetStringVal(PhotoAlbumColumns::ALBUM_NAME, resultSet));
500         PhotoAlbumVector.back()->SetDateModified(GetInt64Val(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, resultSet));
501         PhotoAlbumVector.back()->SetContainsHidden(GetInt32Val(PhotoAlbumColumns::CONTAINS_HIDDEN, resultSet));
502         PhotoAlbumVector.back()->SetOrder(GetInt32Val(PhotoAlbumColumns::ALBUM_ORDER, resultSet));
503         PhotoAlbumVector.back()->SetBundleName(GetStringVal(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, resultSet));
504         PhotoAlbumVector.back()->SetLocalLanguage(GetStringVal(PhotoAlbumColumns::ALBUM_LOCAL_LANGUAGE, resultSet));
505         PhotoAlbumVector.back()->SetDateAdded(GetInt64Val(PhotoAlbumColumns::ALBUM_DATE_ADDED, resultSet));
506         PhotoAlbumVector.back()->SetIsLocal(GetInt32Val(PhotoAlbumColumns::ALBUM_IS_LOCAL, resultSet));
507         PhotoAlbumVector.back()->SetLPath(GetStringVal(PhotoAlbumColumns::ALBUM_LPATH, resultSet));
508         PhotoAlbumVector.back()->SetPriority(GetInt32Val(PhotoAlbumColumns::ALBUM_PRIORITY, resultSet));
509         PhotoAlbumVector.back()->SetAlbumId(GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet));
510     }
511     return E_OK;
512 }
513 
CheckExist(const std::string & path)514 int32_t MediaLibraryAssetOperations::CheckExist(const std::string &path)
515 {
516     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
517     vector<string> columns = {MediaColumn::MEDIA_FILE_PATH};
518 
519     MEDIA_DEBUG_LOG("query media_file_path=%{public}s start\n", DfxUtils::GetSafePath(path).c_str());
520     predicates.EqualTo(PhotoColumn::MEDIA_FILE_PATH, path);
521 
522     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
523     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "MediaLibraryPhotoOperations error\n");
524 
525     int rowCount = 0;
526     if (resultSet->GetRowCount(rowCount) != NativeRdb::E_OK) {
527         MEDIA_ERR_LOG("GetRowCount error\n");
528         return E_HAS_DB_ERROR;
529     }
530 
531     MEDIA_INFO_LOG("query media_file_path end, rowCount=%{public}d\n", rowCount);
532     return (rowCount > 0) ? E_OK : E_FAIL;
533 }
534 
GetPhotosTableColumnInfo()535 const std::vector<std::string> &MediaLibraryAssetOperations::GetPhotosTableColumnInfo()
536 {
537     MEDIA_DEBUG_LOG("GetPhotosTableColumnInfo");
538     static std::vector<std::string> PHOTOS_TABLE_COLUMNS = QueryPhotosTableColumnInfo();
539     if (PHOTOS_TABLE_COLUMNS.empty()) {
540         MEDIA_ERR_LOG("QueryPhotosTableColumnInfo failed");
541         PHOTOS_TABLE_COLUMNS = QueryPhotosTableColumnInfo();
542     }
543 
544     return PHOTOS_TABLE_COLUMNS;
545 }
546 
QueryPhotosTableColumnInfo()547 std::vector<std::string> MediaLibraryAssetOperations::QueryPhotosTableColumnInfo()
548 {
549     MEDIA_DEBUG_LOG("QueryPhotosTableColumnInfo");
550     std::vector<std::string> columnInfo;
551     std::shared_ptr<MediaLibraryRdbStore> rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
552     if (rdbStore == nullptr) {
553         MEDIA_ERR_LOG("rdbStore == nullptr");
554         return columnInfo;
555     }
556 
557     std::string querySql = "SELECT name FROM pragma_table_info('" + PhotoColumn::PHOTOS_TABLE + "')";
558     std::vector<std::string> sqlArgs;
559     auto resultSet = rdbStore->QuerySql(querySql, sqlArgs);
560     if (resultSet == nullptr) {
561         MEDIA_ERR_LOG("resultSet is nullptr");
562         return columnInfo;
563     }
564 
565     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
566         std::string columnName = GetStringVal("name", resultSet);
567         if (FILEASSET_MEMBER_MAP.count(columnName) == 0) {
568             MEDIA_WARN_LOG("FILEASSET_MEMBER_MAP not find column: %{public}s", columnName.c_str());
569             continue;
570         }
571         columnInfo.emplace_back(columnName);
572     }
573 
574     return columnInfo;
575 }
576 
QueryTotalPhoto(vector<shared_ptr<FileAsset>> & fileAssetVector,int32_t batchSize)577 int32_t MediaLibraryAssetOperations::QueryTotalPhoto(vector<shared_ptr<FileAsset>> &fileAssetVector,
578     int32_t batchSize)
579 {
580     MEDIA_INFO_LOG("query total photo start\n");
581     const std::vector<std::string> &columnInfo = GetPhotosTableColumnInfo();
582     if (columnInfo.empty()) {
583         MEDIA_ERR_LOG("GetPhotosTableColumnInfo failed");
584         return E_ERR;
585     }
586 
587     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
588     predicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_METADATA_FLAGS, static_cast<int>(MetadataFlags::TYPE_NEW))->Or()
589         ->EqualTo(PhotoColumn::PHOTO_METADATA_FLAGS, static_cast<int>(MetadataFlags::TYPE_DIRTY))->Or()
590         ->IsNull(PhotoColumn::PHOTO_METADATA_FLAGS)->EndWrap();
591     predicates.And()->BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()
592         ->EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
593     predicates.OrderByAsc(PhotoColumn::PHOTO_METADATA_FLAGS);
594     predicates.Limit(0, batchSize);
595     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columnInfo);
596     if (resultSet == nullptr) {
597         MEDIA_ERR_LOG("MediaLibraryPhotoOperations error\n");
598         return E_OK;
599     }
600 
601     GetAssetVectorFromResultSet(resultSet, columnInfo, fileAssetVector);
602 
603     MEDIA_INFO_LOG("query total photo end\n");
604     return E_OK;
605 }
606 
QuerySinglePhoto(int32_t rowId)607 std::shared_ptr<FileAsset> MediaLibraryAssetOperations::QuerySinglePhoto(int32_t rowId)
608 {
609     const std::vector<std::string> &columnInfo = GetPhotosTableColumnInfo();
610     if (columnInfo.empty()) {
611         MEDIA_ERR_LOG("GetPhotosTableColumnInfo failed");
612         return nullptr;
613     }
614 
615     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
616     predicates.EqualTo(MediaColumn::MEDIA_ID, rowId);
617     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columnInfo);
618     if (resultSet == nullptr) {
619         MEDIA_ERR_LOG("MediaLibraryPhotoOperations error\n");
620         return nullptr;
621     }
622 
623     return GetAssetFromResultSet(resultSet, columnInfo);
624 }
625 
QueryTotalAlbum(vector<shared_ptr<PhotoAlbum>> & photoAlbumVector)626 int32_t MediaLibraryAssetOperations::QueryTotalAlbum(vector<shared_ptr<PhotoAlbum>> &photoAlbumVector)
627 {
628     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
629     vector<string> columns = {PhotoAlbumColumns::ALBUM_ID,
630         PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE,
631         PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_DATE_MODIFIED,
632         PhotoAlbumColumns::CONTAINS_HIDDEN, PhotoAlbumColumns::ALBUM_ORDER,
633         PhotoAlbumColumns::ALBUM_BUNDLE_NAME, PhotoAlbumColumns::ALBUM_LOCAL_LANGUAGE,
634         PhotoAlbumColumns::ALBUM_IS_LOCAL, PhotoAlbumColumns::ALBUM_DATE_ADDED,
635         PhotoAlbumColumns::ALBUM_LPATH, PhotoAlbumColumns::ALBUM_PRIORITY};
636 
637     MEDIA_INFO_LOG("Start query total photo album");
638     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
639     if (resultSet == nullptr) {
640         MEDIA_ERR_LOG("Query failed, resultSet is null");
641         return E_INVALID_ARGUMENTS;
642     }
643 
644     return GetAlbumVectorFromResultSet(resultSet, columns, photoAlbumVector);
645 }
646 
GetFileAssetFromDb(const string & column,const string & value,OperationObject oprnObject,const vector<string> & columns,const string & networkId)647 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(const string &column,
648     const string &value, OperationObject oprnObject, const vector<string> &columns, const string &networkId)
649 {
650     MediaLibraryTracer tracer;
651     tracer.Start("MediaLibraryAssetOperations::GetFileAssetFromDb");
652     if (!CheckOprnObject(oprnObject) || column.empty() || value.empty()) {
653         return nullptr;
654     }
655 
656     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
657     if (rdbStore == nullptr) {
658         return nullptr;
659     }
660 
661     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
662     cmd.GetAbsRdbPredicates()->EqualTo(column, value);
663 
664     auto resultSet = rdbStore->Query(cmd, columns);
665     if (resultSet == nullptr) {
666         return nullptr;
667     }
668     return GetAssetFromResultSet(resultSet, columns);
669 }
670 
QueryByPredicates(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)671 static shared_ptr<NativeRdb::ResultSet> QueryByPredicates(AbsPredicates &predicates,
672     OperationObject oprnObject, const vector<string> &columns, const string &networkId)
673 {
674     if (!CheckOprnObject(oprnObject)) {
675         return nullptr;
676     }
677 
678     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
679     if (rdbStore == nullptr) {
680         return nullptr;
681     }
682 
683     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
684     cmd.GetAbsRdbPredicates()->SetWhereClause(predicates.GetWhereClause());
685     cmd.GetAbsRdbPredicates()->SetWhereArgs(predicates.GetWhereArgs());
686     cmd.GetAbsRdbPredicates()->SetOrder(predicates.GetOrder());
687     return rdbStore->Query(cmd, columns);
688 }
689 
GetFileAssetFromDb(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)690 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(AbsPredicates &predicates,
691     OperationObject oprnObject, const vector<string> &columns, const string &networkId)
692 {
693     auto resultSet = QueryByPredicates(predicates, oprnObject, columns, networkId);
694     if (resultSet == nullptr) {
695         return nullptr;
696     }
697     return GetAssetFromResultSet(resultSet, columns);
698 }
699 
GetFileAssetVectorFromDb(AbsPredicates & predicates,OperationObject oprnObject,vector<shared_ptr<FileAsset>> & fileAssetVector,const vector<string> & columns,const string & networkId)700 int32_t MediaLibraryAssetOperations::GetFileAssetVectorFromDb(AbsPredicates &predicates, OperationObject oprnObject,
701     vector<shared_ptr<FileAsset>> &fileAssetVector, const vector<string> &columns, const string &networkId)
702 {
703     auto resultSet = QueryByPredicates(predicates, oprnObject, columns, networkId);
704     if (resultSet == nullptr) {
705         return E_HAS_DB_ERROR;
706     }
707     return GetAssetVectorFromResultSet(resultSet, columns, fileAssetVector);
708 }
709 
GetFileAssetByUri(const string & uri,bool isPhoto,const std::vector<std::string> & columns,const string & pendingStatus)710 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetByUri(const string &uri, bool isPhoto,
711     const std::vector<std::string> &columns, const string &pendingStatus)
712 {
713     if (uri.empty()) {
714         MEDIA_ERR_LOG("fileUri is empty");
715         return nullptr;
716     }
717 
718     string id = MediaFileUtils::GetIdFromUri(uri);
719     if (uri.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
720         return nullptr;
721     }
722     shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
723     MediaFileUri fileUri(uri);
724     if (pendingStatus.empty() || !fileUri.IsApi10()) {
725         if (isPhoto) {
726             fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_PHOTO, columns);
727         } else {
728             fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_AUDIO, columns);
729         }
730     } else {
731         string path = MediaFileUri::GetPathFromUri(uri, isPhoto);
732         if (path.empty()) {
733             if (isPhoto) {
734                 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_PHOTO, columns);
735             } else {
736                 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_AUDIO, columns);
737             }
738         } else {
739             fileAsset->SetPath(path);
740             fileAsset->SetMediaType(MediaFileUtils::GetMediaType(path));
741             if (MediaFileUtils::IsValidInteger(pendingStatus)) {
742                 int32_t timePending = stoi(pendingStatus);
743                 fileAsset->SetTimePending((timePending > 0) ? MediaFileUtils::UTCTimeSeconds() : timePending);
744             }
745         }
746     }
747 
748     if (fileAsset == nullptr) {
749         return nullptr;
750     }
751     if (!isPhoto) {
752         fileAsset->SetMediaType(MediaType::MEDIA_TYPE_AUDIO);
753     }
754     if (MediaFileUtils::IsValidInteger(id)) {
755         fileAsset->SetId(stoi(id));
756     }
757     fileAsset->SetUri(uri);
758     return fileAsset;
759 }
760 
GetVirtualPath(const string & relativePath,const string & displayName)761 static inline string GetVirtualPath(const string &relativePath, const string &displayName)
762 {
763     if (relativePath[relativePath.size() - 1] != SLASH_CHAR) {
764         return relativePath + SLASH_CHAR + displayName;
765     } else {
766         return relativePath + displayName;
767     }
768 }
769 
GetAssetPackageName(const FileAsset & fileAsset,const string & bundleName)770 static string GetAssetPackageName(const FileAsset &fileAsset, const string &bundleName)
771 {
772     if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::SCREENSHOT)) {
773         if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE) ||
774             fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_PHOTO)) {
775             return "截图";
776         } else if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
777             return "屏幕录制";
778         }
779     }
780     return PermissionUtils::GetPackageNameByBundleName(bundleName);
781 }
782 
HandleDateAdded(const int64_t dateAdded,const MediaType type,ValuesBucket & outValues)783 static void HandleDateAdded(const int64_t dateAdded, const MediaType type, ValuesBucket &outValues)
784 {
785     outValues.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
786     if (type != MEDIA_TYPE_PHOTO) {
787         return;
788     }
789     outValues.PutString(PhotoColumn::PHOTO_DATE_YEAR,
790         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_YEAR_FORMAT, dateAdded));
791     outValues.PutString(PhotoColumn::PHOTO_DATE_MONTH,
792         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_MONTH_FORMAT, dateAdded));
793     outValues.PutString(PhotoColumn::PHOTO_DATE_DAY,
794         MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_DAY_FORMAT, dateAdded));
795     outValues.PutLong(MediaColumn::MEDIA_DATE_TAKEN, dateAdded);
796 }
797 
HandleOwnerAlbumId(MediaLibraryCommand & cmd,ValuesBucket & outValues)798 static void HandleOwnerAlbumId(MediaLibraryCommand &cmd, ValuesBucket &outValues)
799 {
800     string ownerAlbumId;
801     ValueObject valueOwnerAlbumId;
802     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, valueOwnerAlbumId)) {
803         valueOwnerAlbumId.GetString(ownerAlbumId);
804     }
805     if (!ownerAlbumId.empty()) {
806         outValues.PutString(PhotoColumn::PHOTO_OWNER_ALBUM_ID, ownerAlbumId);
807         MEDIA_INFO_LOG("insert ownerAlbumId: %{public}s", ownerAlbumId.c_str());
808     }
809 }
810 
HandleCallingPackage(MediaLibraryCommand & cmd,const FileAsset & fileAsset,ValuesBucket & outValues)811 static void HandleCallingPackage(MediaLibraryCommand &cmd, const FileAsset &fileAsset, ValuesBucket &outValues)
812 {
813     if (!fileAsset.GetOwnerPackage().empty() && PermissionUtils::IsNativeSAApp()) {
814         outValues.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileAsset.GetOwnerPackage());
815 
816         int32_t callingUid = 0;
817         ValueObject value;
818         if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
819             value.GetInt(callingUid);
820         }
821         outValues.PutString(MediaColumn::MEDIA_OWNER_APPID,
822             PermissionUtils::GetAppIdByBundleName(fileAsset.GetOwnerPackage(), callingUid));
823         outValues.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileAsset.GetPackageName());
824         return;
825     }
826 
827     string bundleName;
828     ValueObject valueBundleName;
829     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_OWNER_PACKAGE, valueBundleName)) {
830         valueBundleName.GetString(bundleName);
831     }
832     if (bundleName.empty()) {
833         bundleName = cmd.GetBundleName();
834     }
835     outValues.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, bundleName);
836 
837     string appId;
838     ValueObject valueAppId;
839     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_OWNER_APPID, valueAppId)) {
840         valueAppId.GetString(appId);
841     }
842     if (appId.empty()) {
843         appId = PermissionUtils::GetAppIdByBundleName(cmd.GetBundleName());
844     }
845     outValues.PutString(MediaColumn::MEDIA_OWNER_APPID, appId);
846     string packageName;
847     ValueObject valuePackageName;
848     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_PACKAGE_NAME, valuePackageName)) {
849         valuePackageName.GetString(packageName);
850     }
851     if (packageName.empty() && !cmd.GetBundleName().empty()) {
852         packageName = GetAssetPackageName(fileAsset, cmd.GetBundleName());
853     }
854     if (!packageName.empty()) {
855         outValues.PutString(MediaColumn::MEDIA_PACKAGE_NAME, packageName);
856     }
857     HandleOwnerAlbumId(cmd, outValues);
858 }
859 
HandleBurstPhoto(MediaLibraryCommand & cmd,ValuesBucket & outValues,const std::string displayName)860 static void HandleBurstPhoto(MediaLibraryCommand &cmd, ValuesBucket &outValues, const std::string displayName)
861 {
862     CHECK_AND_RETURN_LOG(PermissionUtils::IsNativeSAApp(),
863         "do not have permission to set burst_key or burst_cover_level");
864 
865     string burstKey;
866     ValueObject value;
867     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_BURST_KEY, value)) {
868         value.GetString(burstKey);
869     }
870     if (!burstKey.empty()) {
871         outValues.PutString(PhotoColumn::PHOTO_BURST_KEY, burstKey);
872     }
873 
874     int32_t burstCoverLevel = 0;
875     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_BURST_COVER_LEVEL, value)) {
876         value.GetInt(burstCoverLevel);
877     }
878     if (burstCoverLevel != 0) {
879         outValues.PutInt(PhotoColumn::PHOTO_BURST_COVER_LEVEL, burstCoverLevel);
880     }
881 
882     int32_t dirty = static_cast<int32_t>(DirtyTypes::TYPE_NEW);
883     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_DIRTY, value)) {
884         value.GetInt(dirty);
885     }
886     if (dirty != static_cast<int32_t>(DirtyTypes::TYPE_NEW)) {
887         outValues.PutInt(PhotoColumn::PHOTO_DIRTY, dirty);
888     }
889     stringstream result;
890     for (size_t i = 0; i < displayName.length(); i++) {
891         if (isdigit(displayName[i])) {
892             result << displayName[i];
893         }
894     }
895     outValues.Put(PhotoColumn::PHOTO_ID, result.str());
896     outValues.PutInt(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
897 }
898 
HandlePhotoInfo(MediaLibraryCommand & cmd,ValuesBucket & outValues,const FileAsset & fileAsset)899 static void HandlePhotoInfo(MediaLibraryCommand &cmd, ValuesBucket &outValues, const FileAsset &fileAsset)
900 {
901     if (!PermissionUtils::IsNativeSAApp()) {
902         MEDIA_DEBUG_LOG("do not have permission to set is_temp");
903         return;
904     }
905 
906     bool isTemp = 0;
907     ValueObject value;
908     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_IS_TEMP, value)) {
909         value.GetBool(isTemp);
910     }
911     outValues.PutBool(PhotoColumn::PHOTO_IS_TEMP, isTemp);
912 
913     int32_t deferredProcType = UNKNOWN_VALUE;
914     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, value)) {
915         value.GetInt(deferredProcType);
916     }
917     if (deferredProcType != UNKNOWN_VALUE) {
918         outValues.PutInt(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, deferredProcType);
919     }
920 
921     // quality、photoId、dirty for burst has been handled in HandleBurstPhoto
922     if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::BURST)) {
923         return;
924     }
925     if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
926         outValues.PutInt(PhotoColumn::STAGE_VIDEO_TASK_STATUS,
927             static_cast<int32_t>(StageVideoTaskStatus::NEED_TO_STAGE));
928     }
929 
930     int32_t photoQuality = UNKNOWN_VALUE;
931     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_QUALITY, value)) {
932         value.GetInt(photoQuality);
933     }
934     if (photoQuality != UNKNOWN_VALUE) {
935         outValues.PutInt(PhotoColumn::PHOTO_QUALITY, photoQuality);
936     }
937     if (photoQuality == static_cast<int32_t>(MultiStagesPhotoQuality::LOW)) {
938         outValues.PutInt(PhotoColumn::PHOTO_DIRTY, -1); // prevent uploading low-quality photo
939     }
940 
941     std::string photoId;
942     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_ID, value)) {
943         value.GetString(photoId);
944     }
945     if (!photoId.empty()) {
946         outValues.PutString(PhotoColumn::PHOTO_ID, photoId);
947     }
948 
949     int32_t ceAvailable = static_cast<int32_t>(CloudEnhancementAvailableType::NOT_SUPPORT);
950     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_CE_AVAILABLE, value)) {
951         value.GetInt(ceAvailable);
952         MEDIA_INFO_LOG("set ce_available: %{public}d", ceAvailable);
953     }
954     outValues.PutInt(PhotoColumn::PHOTO_CE_AVAILABLE, ceAvailable);
955 }
956 
FillAssetInfo(MediaLibraryCommand & cmd,const FileAsset & fileAsset)957 static void FillAssetInfo(MediaLibraryCommand &cmd, const FileAsset &fileAsset)
958 {
959     // Fill basic file information into DB
960     const string& displayName = fileAsset.GetDisplayName();
961     int64_t nowTime = MediaFileUtils::UTCTimeMilliSeconds();
962     ValuesBucket assetInfo;
963     assetInfo.PutInt(MediaColumn::MEDIA_TYPE, fileAsset.GetMediaType());
964     string extension = ScannerUtils::GetFileExtension(displayName);
965     assetInfo.PutString(MediaColumn::MEDIA_MIME_TYPE,
966         MimeTypeUtils::GetMimeTypeFromExtension(extension));
967     assetInfo.PutString(MediaColumn::MEDIA_FILE_PATH, fileAsset.GetPath());
968     if (cmd.GetApi() == MediaLibraryApi::API_OLD) {
969         assetInfo.PutString(MediaColumn::MEDIA_RELATIVE_PATH, fileAsset.GetRelativePath());
970         assetInfo.PutString(MediaColumn::MEDIA_VIRTURL_PATH,
971             GetVirtualPath(fileAsset.GetRelativePath(), fileAsset.GetDisplayName()));
972     } else {
973         assetInfo.PutLong(MediaColumn::MEDIA_TIME_PENDING, fileAsset.GetTimePending());
974     }
975     assetInfo.PutString(MediaColumn::MEDIA_NAME, displayName);
976     assetInfo.PutString(MediaColumn::MEDIA_TITLE, MediaFileUtils::GetTitleFromDisplayName(displayName));
977     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
978         assetInfo.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, extension);
979         assetInfo.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileAsset.GetPhotoSubType());
980         assetInfo.PutString(PhotoColumn::CAMERA_SHOT_KEY, fileAsset.GetCameraShotKey());
981         HandlePhotoInfo(cmd, assetInfo, fileAsset);
982         if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::BURST)) {
983             HandleBurstPhoto(cmd, assetInfo, displayName);
984         }
985     }
986 
987     HandleCallingPackage(cmd, fileAsset, assetInfo);
988 
989     assetInfo.PutString(MediaColumn::MEDIA_DEVICE_NAME, cmd.GetDeviceName());
990     HandleDateAdded(nowTime,
991         cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO ? MEDIA_TYPE_PHOTO : MEDIA_TYPE_DEFAULT,
992         assetInfo);
993     cmd.SetValueBucket(assetInfo);
994 }
995 
GetOwnerPermissionBucket(MediaLibraryCommand & cmd,int64_t fileId,int32_t callingUid)996 static ValuesBucket GetOwnerPermissionBucket(MediaLibraryCommand &cmd, int64_t fileId, int32_t callingUid)
997 {
998     int64_t tokenId = 0;
999     string tokenIdFromClient = cmd.GetQuerySetParam("tokenId");
1000     tokenId = static_cast<int64_t>(std::atoi(tokenIdFromClient.c_str()));
1001     if (tokenId == 0) {
1002         if (callingUid > 0 && PermissionUtils::IsNativeSAApp()) {
1003             string bundleName;
1004             PermissionUtils::GetClientBundle(callingUid, bundleName);
1005             string appId = PermissionUtils::GetAppIdByBundleName(bundleName, callingUid);
1006             PermissionUtils::GetMainTokenId(appId, tokenId);
1007         }
1008     }
1009     if (tokenId == 0) {
1010         tokenId = PermissionUtils::GetTokenId();
1011     }
1012     string tableName = cmd.GetTableName();
1013     TableType mediaType;
1014     if (tableName == PhotoColumn::PHOTOS_TABLE) {
1015         mediaType = TableType::TYPE_PHOTOS;
1016     } else {
1017         mediaType = TableType::TYPE_AUDIOS;
1018     }
1019     ValuesBucket valuesBucket;
1020     valuesBucket.Put(AppUriPermissionColumn::FILE_ID, static_cast<int32_t>(fileId));
1021     valuesBucket.Put(AppUriPermissionColumn::URI_TYPE, static_cast<int32_t>(mediaType));
1022     valuesBucket.Put(AppUriPermissionColumn::PERMISSION_TYPE,
1023         AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE);
1024     valuesBucket.Put(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)tokenId);
1025     valuesBucket.Put(AppUriPermissionColumn::SOURCE_TOKENID, (int64_t)tokenId);
1026     valuesBucket.Put(AppUriPermissionColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1027     return valuesBucket;
1028 }
1029 
InsertAssetInDb(std::shared_ptr<TransactionOperations> trans,MediaLibraryCommand & cmd,const FileAsset & fileAsset)1030 int32_t MediaLibraryAssetOperations::InsertAssetInDb(std::shared_ptr<TransactionOperations> trans,
1031     MediaLibraryCommand &cmd, const FileAsset &fileAsset)
1032 {
1033     // All values inserted in this function are the base property for files
1034     if (trans == nullptr) {
1035         return E_HAS_DB_ERROR;
1036     }
1037 
1038     if (!fileAsset.GetPath().empty() && MediaFileUtils::IsFileExists(fileAsset.GetPath())) {
1039         MEDIA_ERR_LOG("file %{private}s exists now", fileAsset.GetPath().c_str());
1040         return E_FILE_EXIST;
1041     }
1042     int32_t callingUid = 0;
1043     ValueObject value;
1044     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
1045         value.GetInt(callingUid);
1046     }
1047     FillAssetInfo(cmd, fileAsset);
1048 
1049     int64_t outRowId = -1;
1050     int32_t errCode = trans->Insert(cmd, outRowId);
1051     if (errCode != NativeRdb::E_OK) {
1052         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
1053         return E_HAS_DB_ERROR;
1054     }
1055     MEDIA_INFO_LOG("insert success, rowId = %{public}d", (int)outRowId);
1056     auto fileId = outRowId;
1057     ValuesBucket valuesBucket = GetOwnerPermissionBucket(cmd, fileId, callingUid);
1058     int64_t tmpOutRowId = -1;
1059     MediaLibraryCommand cmdPermission(Uri(MEDIALIBRARY_GRANT_URIPERM_URI), valuesBucket);
1060     errCode = trans->Insert(cmdPermission, tmpOutRowId);
1061     if (errCode != NativeRdb::E_OK) {
1062         MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
1063         return E_HAS_DB_ERROR;
1064     }
1065     MEDIA_INFO_LOG("insert uripermission success, rowId = %{public}d", (int)tmpOutRowId);
1066     return static_cast<int32_t>(outRowId);
1067 }
1068 
CheckTypeFromRootDir(const std::string & rootDirName,int32_t type)1069 static bool CheckTypeFromRootDir(const std::string &rootDirName, int32_t type)
1070 {
1071     // "Camera/"
1072     if (!strcmp(rootDirName.c_str(), CAMERA_DIR_VALUES.c_str())) {
1073         if (type == MEDIA_TYPE_IMAGE || type == MEDIA_TYPE_VIDEO) {
1074             return true;
1075         }
1076     }
1077     // "Videos/"
1078     if (!strcmp(rootDirName.c_str(), VIDEO_DIR_VALUES.c_str())) {
1079         if (type == MEDIA_TYPE_VIDEO) {
1080             return true;
1081         }
1082     }
1083     // "Pictures/"
1084     if (!strcmp(rootDirName.c_str(), PIC_DIR_VALUES.c_str())) {
1085         if (type == MEDIA_TYPE_IMAGE) {
1086             return true;
1087         }
1088     }
1089     // "Audios/"
1090     if (!strcmp(rootDirName.c_str(), AUDIO_DIR_VALUES.c_str())) {
1091         if (type == MEDIA_TYPE_AUDIO) {
1092             return true;
1093         }
1094     }
1095     // "Docs/Documents/" and "Docs/Download"
1096     if (!strcmp(rootDirName.c_str(), DOCS_PATH.c_str())) {
1097         return true;
1098     }
1099     MEDIA_ERR_LOG("Cannot match rootDir %{private}s and mediaType %{public}d",
1100         rootDirName.c_str(), type);
1101     return false;
1102 }
1103 
CheckWithType(bool isContains,const string & displayName,const string & extention,int32_t mediaType)1104 int32_t MediaLibraryAssetOperations::CheckWithType(bool isContains, const string &displayName,
1105     const string &extention, int32_t mediaType)
1106 {
1107     string name = isContains ? displayName : extention;
1108     int32_t errCode =  isContains ? CheckDisplayNameWithType(name, mediaType) : CheckExtWithType(name, mediaType);
1109     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1110         "Failed to Check Dir and extention, (displayName or extention)=%{private}s, mediaType=%{public}d",
1111         name.c_str(), mediaType);
1112     return errCode;
1113 }
1114 
CheckDisplayNameWithType(const string & displayName,int32_t mediaType)1115 int32_t MediaLibraryAssetOperations::CheckDisplayNameWithType(const string &displayName, int32_t mediaType)
1116 {
1117     int32_t ret = MediaFileUtils::CheckDisplayName(displayName);
1118     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_DISPLAY_NAME, "Check DisplayName failed, "
1119         "displayName=%{private}s", displayName.c_str());
1120 
1121     string ext = MediaFileUtils::GetExtensionFromPath(displayName);
1122     CHECK_AND_RETURN_RET_LOG(!ext.empty(), E_INVALID_DISPLAY_NAME, "invalid extension, displayName=%{private}s",
1123         displayName.c_str());
1124 
1125     auto typeFromExt = MediaFileUtils::GetMediaType(displayName);
1126     CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
1127         "cannot match, mediaType=%{public}d, ext=%{private}s, type from ext=%{public}d",
1128         mediaType, ext.c_str(), typeFromExt);
1129     return E_OK;
1130 }
1131 
CheckExtWithType(const string & extention,int32_t mediaType)1132 int32_t MediaLibraryAssetOperations::CheckExtWithType(const string &extention, int32_t mediaType)
1133 {
1134     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention);
1135     auto typeFromExt = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1136     CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
1137         "cannot match, mediaType=%{public}d, ext=%{public}s, type from ext=%{public}d",
1138         mediaType, extention.c_str(), typeFromExt);
1139     return E_OK;
1140 }
1141 
CheckRelativePathWithType(const string & relativePath,int32_t mediaType)1142 int32_t MediaLibraryAssetOperations::CheckRelativePathWithType(const string &relativePath, int32_t mediaType)
1143 {
1144     int32_t ret = MediaFileUtils::CheckRelativePath(relativePath);
1145     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_PATH, "Check relativePath failed, "
1146         "relativePath=%{private}s", relativePath.c_str());
1147 
1148     // get rootdir and check if it match mediatype
1149     string rootDirName;
1150     MediaFileUtils::GetRootDirFromRelativePath(relativePath, rootDirName);
1151     CHECK_AND_RETURN_RET_LOG(!rootDirName.empty(), E_INVALID_PATH, "Cannot get rootdirName");
1152 
1153     bool isValid = CheckTypeFromRootDir(rootDirName, mediaType);
1154     CHECK_AND_RETURN_RET(isValid, E_CHECK_MEDIATYPE_FAIL);
1155     return E_OK;
1156 }
1157 
GetAssetRootDir(int32_t mediaType,string & rootDirPath)1158 void MediaLibraryAssetOperations::GetAssetRootDir(int32_t mediaType, string &rootDirPath)
1159 {
1160     map<int, string> rootDir = {
1161         { MEDIA_TYPE_FILE, DOCUMENT_BUCKET + SLASH_CHAR },
1162         { MEDIA_TYPE_VIDEO, PHOTO_BUCKET + SLASH_CHAR },
1163         { MEDIA_TYPE_IMAGE, PHOTO_BUCKET + SLASH_CHAR },
1164         { MEDIA_TYPE_AUDIO, AUDIO_BUCKET + SLASH_CHAR },
1165     };
1166     if (rootDir.count(mediaType) == 0) {
1167         rootDirPath = rootDir[MEDIA_TYPE_FILE];
1168     } else {
1169         rootDirPath = rootDir[mediaType];
1170     }
1171 }
1172 
SetAssetPathInCreate(FileAsset & fileAsset,std::shared_ptr<TransactionOperations> trans)1173 int32_t MediaLibraryAssetOperations::SetAssetPathInCreate(FileAsset &fileAsset,
1174     std::shared_ptr<TransactionOperations> trans)
1175 {
1176     if (!fileAsset.GetPath().empty()) {
1177         return E_OK;
1178     }
1179     string extension = MediaFileUtils::GetExtensionFromPath(fileAsset.GetDisplayName());
1180     string filePath;
1181     int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType(), trans);
1182     int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
1183     if (errCode != E_OK) {
1184         MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
1185         return errCode;
1186     }
1187 
1188     // filePath can not be empty
1189     fileAsset.SetPath(filePath);
1190     return E_OK;
1191 }
1192 
SetAssetPath(FileAsset & fileAsset,const string & extension,std::shared_ptr<TransactionOperations> trans)1193 int32_t MediaLibraryAssetOperations::SetAssetPath(FileAsset &fileAsset, const string &extension,
1194     std::shared_ptr<TransactionOperations> trans)
1195 {
1196     string filePath;
1197     int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType(), trans);
1198     int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
1199     if (errCode != E_OK) {
1200         MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
1201         return errCode;
1202     }
1203 
1204     // filePath can not be empty
1205     fileAsset.SetPath(filePath);
1206     string fileName = MediaFileUtils::GetFileName(filePath);
1207     string displayName = fileName.substr(0, fileName.find('_')) + '_' + fileName.substr(fileName.rfind('_') + 1);
1208     fileAsset.SetDisplayName(displayName);
1209     return E_OK;
1210 }
1211 
DeleteAssetInDb(MediaLibraryCommand & cmd)1212 int32_t MediaLibraryAssetOperations::DeleteAssetInDb(MediaLibraryCommand &cmd)
1213 {
1214     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1215     if (rdbStore == nullptr) {
1216         return E_HAS_DB_ERROR;
1217     }
1218 
1219     string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1220     if (strDeleteCondition.empty()) {
1221         string strRow = cmd.GetOprnFileId();
1222         if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow)) {
1223             MEDIA_ERR_LOG("MediaLibraryAssetOperations DeleteFile: Index not digit, fileIdStr=%{private}s",
1224                 strRow.c_str());
1225             return E_INVALID_FILEID;
1226         }
1227         cmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, strRow);
1228     }
1229 
1230     int32_t deletedRows = E_HAS_DB_ERROR;
1231     int32_t result = rdbStore->Delete(cmd, deletedRows);
1232     if (result != NativeRdb::E_OK) {
1233         MEDIA_ERR_LOG("Delete operation failed. Result %{public}d.", result);
1234     }
1235 
1236     return deletedRows;
1237 }
1238 
IsSetDisplayName(MediaLibraryCommand & cmd)1239 bool MediaLibraryAssetOperations::IsSetDisplayName(MediaLibraryCommand &cmd)
1240 {
1241     std::string newDisplayName = cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY);
1242     CHECK_AND_RETURN_RET(!newDisplayName.empty(), false);
1243     MEDIA_INFO_LOG("new display name is %{public}s.", newDisplayName.c_str());
1244     return true;
1245 }
1246 
CheckUriBySetDisplayName(MediaLibraryCommand & cmd)1247 bool MediaLibraryAssetOperations::CheckUriBySetDisplayName(MediaLibraryCommand &cmd)
1248 {
1249     CHECK_AND_RETURN_RET(IsSetDisplayName(cmd), false);
1250 
1251     std::string oldDisplayName = cmd.GetQuerySetParam(OLD_DISPLAY_NAME);
1252     CHECK_AND_RETURN_RET_LOG(!oldDisplayName.empty(), false,
1253         "Failed to setDisplayName, due to uri is not contain old displayName");
1254     MEDIA_INFO_LOG("Old display name is %{public}s.", oldDisplayName.c_str());
1255 
1256     std::string isCallFallback = cmd.GetQuerySetParam(CAN_FALLBACK);
1257     CHECK_AND_RETURN_RET_LOG(!isCallFallback.empty(), false,
1258         "Failed to setDisplayName, due to uri is not contain can_fallback.");
1259     return true;
1260 }
1261 
UpdateFileName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)1262 int32_t MediaLibraryAssetOperations::UpdateFileName(MediaLibraryCommand &cmd,
1263     const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
1264 {
1265     // if uri contains "set_displayName", it will do ChangeDisplayName();
1266     CHECK_AND_RETURN_RET(!IsSetDisplayName(cmd), ChangeDisplayName(cmd, fileAsset, isNameChanged));
1267     ValuesBucket &values = cmd.GetValueBucket();
1268     ValueObject valueObject;
1269     string newTitle;
1270     string newDisplayName;
1271     bool containsTitle = false;
1272     bool containsDisplayName = false;
1273 
1274     if (values.GetObject(MediaColumn::MEDIA_TITLE, valueObject)) {
1275         valueObject.GetString(newTitle);
1276         containsTitle = true;
1277     }
1278     if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
1279         valueObject.GetString(newDisplayName);
1280         containsDisplayName = true;
1281     }
1282     if ((!containsTitle) && (!containsDisplayName)) {
1283         // do not need to update
1284         return E_OK;
1285     }
1286     if (containsTitle && containsDisplayName &&
1287         (MediaFileUtils::GetTitleFromDisplayName(newDisplayName) != newTitle)) {
1288         MEDIA_ERR_LOG("new displayName [%{private}s] and new title [%{private}s] is not same",
1289             newDisplayName.c_str(), newTitle.c_str());
1290         return E_INVALID_DISPLAY_NAME;
1291     }
1292     if (!containsTitle) {
1293         newTitle = MediaFileUtils::GetTitleFromDisplayName(newDisplayName);
1294     }
1295     if (!containsDisplayName) {
1296         newDisplayName = newTitle + "." + MediaFileUtils::SplitByChar(fileAsset->GetDisplayName(), '.');
1297     }
1298 
1299     int32_t ret = CheckDisplayNameWithType(newDisplayName, fileAsset->GetMediaType());
1300     CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Input displayName invalid %{private}s", newDisplayName.c_str());
1301     values.PutString(MediaColumn::MEDIA_TITLE, newTitle);
1302     values.PutString(MediaColumn::MEDIA_NAME, newDisplayName);
1303     if (cmd.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
1304         values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(newDisplayName));
1305     }
1306     isNameChanged = true;
1307     return E_OK;
1308 }
1309 
ChangeDisplayName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)1310 int32_t MediaLibraryAssetOperations::ChangeDisplayName(MediaLibraryCommand &cmd, const shared_ptr<FileAsset> &fileAsset,
1311     bool &isNameChanged)
1312 {
1313     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
1314     CHECK_AND_RETURN_RET_LOG(cmd.GetTableName() == PhotoColumn::PHOTOS_TABLE, E_INVALID_VALUES, "invalid input table");
1315     CHECK_AND_RETURN_RET_LOG(CheckUriBySetDisplayName(cmd), E_INVALID_VALUES, "invalid input uri");
1316     NativeRdb::ValuesBucket values;
1317     std::string newDisplayName = cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY);
1318     CHECK_AND_RETURN_RET_LOG(GetUpdateValuesBucket(cmd, fileAsset, values) == E_OK,
1319         E_INVALID_VALUES, "Invalid display name: %{public}s.", newDisplayName.c_str());
1320     cmd.SetValueBucket(values);
1321     isNameChanged = true;
1322     return E_OK;
1323 }
1324 
GetUpdateValuesBucket(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,NativeRdb::ValuesBucket & values)1325 int32_t MediaLibraryAssetOperations::GetUpdateValuesBucket(
1326     MediaLibraryCommand &cmd, const shared_ptr<FileAsset> &fileAsset, NativeRdb::ValuesBucket &values)
1327 {
1328     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
1329     std::string newDisplayName = cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY);
1330     std::string newTitle = MediaFileUtils::GetTitleFromDisplayName(newDisplayName);
1331     std::string newMimeType = MediaFileUtils::GetMimeTypeFromDisplayName(newDisplayName);
1332     std::string newExtension = MediaFileUtils::GetExtensionFromPath(newDisplayName);
1333     std::string newPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." + newExtension;
1334     CHECK_AND_RETURN_RET_LOG(CheckDisplayNameWithType(newDisplayName, fileAsset->GetMediaType()) == E_OK,
1335         E_INVALID_VALUES, "Invalid display name: %{public}s.", newDisplayName.c_str());
1336     values.PutString(MediaColumn::MEDIA_NAME, newDisplayName);
1337     values.PutString(MediaColumn::MEDIA_TITLE, newTitle);
1338     values.PutString(MediaColumn::MEDIA_FILE_PATH, newPath);
1339     values.PutString(MediaColumn::MEDIA_MIME_TYPE, newMimeType);
1340     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, newExtension);
1341     if (fileAsset->GetDirty() == static_cast<int32_t>(DirtyTypes::TYPE_SYNCED)) {
1342         values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_FDIRTY));
1343     }
1344     MEDIA_INFO_LOG("wang do: newDisplayName: %{public}s.", newDisplayName.c_str());
1345     return E_OK;
1346 }
1347 
UpdateDbBySetDisplayName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1348 int32_t MediaLibraryAssetOperations::UpdateDbBySetDisplayName(
1349     MediaLibraryCommand &cmd, const shared_ptr<FileAsset> &fileAsset)
1350 {
1351     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
1352     MEDIA_INFO_LOG("UpdateDbBySetDisplayName enter, fileId: %{public}d.", fileAsset->GetId());
1353     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1354     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_ERR, "Update operation failed. rdbStore is null");
1355     CHECK_AND_RETURN_RET_LOG(CheckUriBySetDisplayName(cmd), E_ERR, "Invalid input uri.");
1356     int32_t id = fileAsset->GetId();
1357     NativeRdb::ValuesBucket valuesBucket;
1358     CHECK_AND_RETURN_RET_LOG(GetUpdateValuesBucket(cmd, fileAsset, valuesBucket) == E_OK, E_INVALID_VALUES,
1359         "invalid input valuesBucket");
1360 
1361     valuesBucket.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, MediaFileUtils::UTCTimeMilliSeconds());
1362     valuesBucket.PutLong(PhotoColumn::PHOTO_META_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1363     valuesBucket.PutLong(PhotoColumn::MEDIA_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1364     std::string whereClauses = MediaColumn::MEDIA_ID + " = ?";
1365     std::vector<std::string> whereArgs = {std::to_string(id)};
1366 
1367     int32_t updateRows = 0;
1368     int32_t ret = rdbStore->Update(updateRows, PhotoColumn::PHOTOS_TABLE, valuesBucket, whereClauses, whereArgs);
1369     CHECK_AND_RETURN_RET_LOG((ret == NativeRdb::E_OK && updateRows >= 0), E_ERR,
1370         "failed to update, ret: %{public}d, updateRows: %{public}d.", ret, updateRows);
1371     MEDIA_INFO_LOG("UpdateDbBySetDisplayName end.");
1372     return ret;
1373 }
1374 
UpdateFileBySetDisplayName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1375 bool MediaLibraryAssetOperations::UpdateFileBySetDisplayName(
1376     MediaLibraryCommand &cmd, const shared_ptr<FileAsset> &fileAsset)
1377 {
1378     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
1379     MEDIA_INFO_LOG("UpdateFileBySetDisplayName enter, fileId: %{public}d.", fileAsset->GetId());
1380     CHECK_AND_RETURN_RET_LOG(CheckUriBySetDisplayName(cmd), false, "Failed to check uri.");
1381     MEDIA_INFO_LOG("UpdateFileBySetDisplayName enter");
1382     std::string newDisplayName = cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY);
1383 
1384     std::string oldPath = fileAsset->GetPath();
1385     std::string newPath =
1386         MediaFileUtils::UnSplitByChar(oldPath, '.') + "." + MediaFileUtils::GetExtensionFromPath(newDisplayName);
1387     if (MediaFileUtils::IsFileExists(newPath)) {
1388         return false;
1389     }
1390     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(oldPath, newPath) == E_OK, false,
1391         "Failed to setDispleyName due to rename filename, title is %{public}s", fileAsset->GetTitle().c_str());
1392     if (!DeleteThumbByFileId(cmd, fileAsset)) {
1393         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(newPath, oldPath) == E_OK,
1394             false, "Failed to rename file: %{private}s", oldPath.c_str());
1395         MEDIA_ERR_LOG("Failed to setDispleyName fail due to delete thumb fail; title is %{public}s",
1396             fileAsset->GetTitle().c_str());
1397         return false;
1398     }
1399     MEDIA_INFO_LOG("UpdateFileBySetDisplayName success.");
1400     return true;
1401 }
1402 
DeleteThumbByFileId(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1403 bool MediaLibraryAssetOperations::DeleteThumbByFileId(MediaLibraryCommand &cmd, const shared_ptr<FileAsset> &fileAsset)
1404 {
1405     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
1406     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1407     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "Update operation failed. rdbStore is null");
1408 
1409     int64_t dataTaken = fileAsset->GetDateTaken();
1410     std::string path = fileAsset->GetPath();
1411     int32_t id = fileAsset->GetId();
1412     bool ret =  ThumbnailService::GetInstance()->HasInvalidateThumbnail(
1413         to_string(id), PhotoColumn::PHOTOS_TABLE, path, to_string(dataTaken));
1414     if (ret) {
1415         int32_t userId = -1;
1416         string thumbPath = MediaFileUtils::GetThumbDir(path, userId);
1417         return MediaFileUtils::DeleteDir(thumbPath);
1418     }
1419     return ret;
1420 }
1421 
RevertSetDisplayName(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset)1422 void MediaLibraryAssetOperations::RevertSetDisplayName(MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset)
1423 {
1424     int32_t id;
1425     if (cmd.GetQuerySetParam(OLD_DISPLAY_NAME) == "1" &&
1426         !GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MEDIA_ID, id)) {
1427         RevertSetDisplayNameByDelete(cmd, fileAsset);
1428     } else {
1429         RevertSetDisplayNameByUpdate(cmd, fileAsset);
1430     }
1431 }
1432 
RevertSetDisplayNameByDelete(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset)1433 void MediaLibraryAssetOperations::RevertSetDisplayNameByDelete(
1434     MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset)
1435 {
1436     CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is nullptr");
1437     string oldDisplayName = cmd.GetQuerySetParam(OLD_DISPLAY_NAME);
1438     string oldPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." +
1439                      MediaFileUtils::GetExtensionFromPath(oldDisplayName);
1440     string newPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." +
1441                      MediaFileUtils::GetExtensionFromPath(cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY));
1442     // 此处回退fileAsset对象中的path和displayname
1443     fileAsset->SetPath(oldPath);
1444     fileAsset->SetDisplayName(oldDisplayName);
1445     if (MediaFileUtils::IsFileExists(newPath)) {
1446         CHECK_AND_RETURN_LOG(MediaFileUtils::ModifyAsset(newPath, oldPath) == E_OK,
1447             "Failed to rename file: %{private}s", oldPath.c_str());
1448     }
1449     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1450     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Update operation failed. rdbStore is null");
1451     int32_t id = fileAsset->GetId();
1452     std::string deleteSetDisplayNameIdSql = "DELETE FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
1453         MediaColumn::MEDIA_ID + " = " + std::to_string(id);
1454     int32_t ret = rdbStore->ExecuteSql(deleteSetDisplayNameIdSql);
1455     CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK, "revert delete when setDisplayName: %{public}s",
1456         cmd.GetQuerySetParam(OLD_DISPLAY_NAME).c_str());
1457     MEDIA_INFO_LOG("RevertSetDisplayNameByDelete success, oldDisplayName: %{public}s.", oldDisplayName.c_str());
1458 }
1459 
RevertSetDisplayNameByUpdate(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset)1460 void MediaLibraryAssetOperations::RevertSetDisplayNameByUpdate(
1461     MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset)
1462 {
1463     CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is nullptr");
1464     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1465     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Update operation failed. rdbStore is null");
1466     int32_t id = fileAsset->GetId();
1467     string oldDisplayName = cmd.GetQuerySetParam(OLD_DISPLAY_NAME);
1468     string oldTitle = MediaFileUtils::GetTitleFromDisplayName(oldDisplayName);
1469     string oldExtension = MediaFileUtils::GetExtensionFromPath(oldDisplayName);
1470     string oldPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." + oldExtension;
1471     string newPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." +
1472                      MediaFileUtils::SplitByChar(cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY), '.');
1473     // 此处回退fileAsset对象中的path和displayname
1474     fileAsset->SetPath(oldPath);
1475     fileAsset->SetDisplayName(oldDisplayName);
1476     if (MediaFileUtils::IsFileExists(newPath)) {
1477         CHECK_AND_RETURN_LOG(MediaFileUtils::ModifyAsset(newPath, oldPath) == E_OK,
1478             "Failed to rename file: %{private}s", oldPath.c_str());
1479     }
1480     NativeRdb::ValuesBucket values;
1481     values.PutString(MediaColumn::MEDIA_NAME, oldDisplayName);
1482     values.PutString(MediaColumn::MEDIA_TITLE, oldTitle);
1483     values.PutString(MediaColumn::MEDIA_FILE_PATH, oldPath);
1484     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, oldExtension);
1485     values.PutString(MediaColumn::MEDIA_MIME_TYPE, fileAsset->GetMimeType());
1486     values.PutInt(PhotoColumn::PHOTO_DIRTY, fileAsset->GetDirty());
1487     std::string whereClauses = MediaColumn::MEDIA_ID + " = ?";
1488     std::vector<std::string> whereArgs = {std::to_string(id)};
1489     int32_t updateRows = 0;
1490     int32_t ret = rdbStore->Update(updateRows, PhotoColumn::PHOTOS_TABLE, values, whereClauses, whereArgs);
1491     CHECK_AND_RETURN_LOG((ret == NativeRdb::E_OK && updateRows >= 0),
1492         "failed to update, ret: %{public}d, updateRows: %{public}d.", ret, updateRows);
1493     MEDIA_INFO_LOG("RevertSetDisplayNameByUpdate success, oldDisplayName: %{public}s.", oldDisplayName.c_str());
1494 }
1495 
SetUserComment(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1496 int32_t MediaLibraryAssetOperations::SetUserComment(MediaLibraryCommand &cmd,
1497     const shared_ptr<FileAsset> &fileAsset)
1498 {
1499     ValuesBucket &values = cmd.GetValueBucket();
1500     ValueObject valueObject;
1501     string newUserComment;
1502 
1503     if (values.GetObject(PhotoColumn::PHOTO_USER_COMMENT, valueObject)) {
1504         valueObject.GetString(newUserComment);
1505     } else {
1506         return E_OK;
1507     }
1508 
1509     uint32_t err = 0;
1510     SourceOptions opts;
1511     string filePath = fileAsset->GetFilePath();
1512     string extension = MediaFileUtils::GetExtensionFromPath(filePath);
1513     opts.formatHint = "image/" + extension;
1514     std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(filePath, opts, err);
1515     if (err != 0 || imageSource == nullptr) {
1516         MEDIA_ERR_LOG("Failed to obtain image source, err = %{public}d", err);
1517         return E_OK;
1518     }
1519 
1520     string userComment;
1521     err = imageSource->GetImagePropertyString(0, PHOTO_DATA_IMAGE_USER_COMMENT, userComment);
1522     CHECK_AND_RETURN_RET_LOG(err == 0, E_OK, "Image does not exist user comment in exif, no need to modify");
1523     err = imageSource->ModifyImageProperty(0, PHOTO_DATA_IMAGE_USER_COMMENT, newUserComment, filePath);
1524     CHECK_AND_PRINT_LOG(err == 0, "Modify image property user comment failed");
1525     return E_OK;
1526 }
1527 
UpdateRelativePath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)1528 int32_t MediaLibraryAssetOperations::UpdateRelativePath(MediaLibraryCommand &cmd,
1529     const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
1530 {
1531     string newRelativePath;
1532     ValuesBucket &values = cmd.GetValueBucket();
1533     ValueObject valueObject;
1534     if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
1535         valueObject.GetString(newRelativePath);
1536     } else {
1537         // relativePath is not modified
1538         return E_OK;
1539     }
1540     MediaFileUtils::FormatRelativePath(newRelativePath);
1541 
1542     if (newRelativePath == fileAsset->GetRelativePath()) {
1543         // relativepath has not been modified
1544         return E_OK;
1545     }
1546 
1547     int32_t errCode = CheckRelativePathWithType(newRelativePath, fileAsset->GetMediaType());
1548     if (errCode != E_SUCCESS) {
1549         MEDIA_ERR_LOG("Check RelativePath failed");
1550         return errCode;
1551     }
1552     values.Delete(MediaColumn::MEDIA_RELATIVE_PATH);
1553     values.PutString(MediaColumn::MEDIA_RELATIVE_PATH, newRelativePath);
1554 
1555     isNameChanged = true;
1556     return E_OK;
1557 }
1558 
UpdateVirtualPath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1559 void MediaLibraryAssetOperations::UpdateVirtualPath(MediaLibraryCommand &cmd,
1560     const shared_ptr<FileAsset> &fileAsset)
1561 {
1562     string relativePath;
1563     string displayName;
1564     ValuesBucket &values = cmd.GetValueBucket();
1565     ValueObject valueObject;
1566 
1567     if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
1568         valueObject.GetString(displayName);
1569     } else {
1570         displayName = fileAsset->GetDisplayName();
1571     }
1572 
1573     if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
1574         valueObject.GetString(relativePath);
1575     } else {
1576         relativePath = fileAsset->GetRelativePath();
1577     }
1578 
1579     if (relativePath.back() != '/') {
1580         relativePath += '/';
1581     }
1582     string virtualPath = relativePath + displayName;
1583     values.PutString(MediaColumn::MEDIA_VIRTURL_PATH, virtualPath);
1584 }
1585 
UpdateFileInDb(MediaLibraryCommand & cmd)1586 int32_t MediaLibraryAssetOperations::UpdateFileInDb(MediaLibraryCommand &cmd)
1587 {
1588     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1589     if (rdbStore == nullptr) {
1590         return E_HAS_DB_ERROR;
1591     }
1592 
1593     int32_t updateRows = 0;
1594     int32_t result = rdbStore->Update(cmd, updateRows);
1595     if (result != NativeRdb::E_OK || updateRows <= 0) {
1596         MEDIA_ERR_LOG("Update File failed. Result %{public}d.", result);
1597         return E_HAS_DB_ERROR;
1598     }
1599 
1600     return updateRows;
1601 }
1602 
OpenFileWithPrivacy(const string & filePath,const string & mode,const string & fileId,int32_t type)1603 int32_t MediaLibraryAssetOperations::OpenFileWithPrivacy(const string &filePath, const string &mode,
1604     const string &fileId, int32_t type)
1605 {
1606     std::string absFilePath;
1607     if (!PathToRealPath(filePath, absFilePath)) {
1608         MEDIA_ERR_LOG("Failed to get real path: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
1609         return E_ERR;
1610     }
1611     MEDIA_DEBUG_LOG("Open with privacy type:%{public}d", type);
1612     return MediaPrivacyManager(absFilePath, mode, fileId, type).Open();
1613 }
1614 
SetPendingTime(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)1615 static int32_t SetPendingTime(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
1616 {
1617     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1618     if (rdbStore == nullptr) {
1619         return E_HAS_DB_ERROR;
1620     }
1621 
1622     MediaLibraryCommand updatePendingCmd(GetOprnObjectByMediaType(fileAsset->GetMediaType()),
1623         OperationType::UPDATE);
1624     updatePendingCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID,
1625         to_string(fileAsset->GetId()));
1626     ValuesBucket values;
1627     values.PutLong(MediaColumn::MEDIA_TIME_PENDING, pendingTime);
1628     updatePendingCmd.SetValueBucket(values);
1629     int32_t rowId = 0;
1630     int32_t result = rdbStore->Update(updatePendingCmd, rowId);
1631     if (result != NativeRdb::E_OK || rowId <= 0) {
1632         MEDIA_ERR_LOG("Update File pending failed. Result %{public}d.", result);
1633         return E_HAS_DB_ERROR;
1634     }
1635     return E_OK;
1636 }
1637 
CreateFileAndSetPending(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)1638 static int32_t CreateFileAndSetPending(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
1639 {
1640     int32_t errCode = MediaFileUtils::CreateAsset(fileAsset->GetPath());
1641     if (errCode != E_OK) {
1642         MEDIA_ERR_LOG("Create asset failed, path=%{private}s", fileAsset->GetPath().c_str());
1643         return errCode;
1644     }
1645 
1646     return SetPendingTime(fileAsset, pendingTime);
1647 }
1648 
SolvePendingStatus(const shared_ptr<FileAsset> & fileAsset,const string & mode)1649 static int32_t SolvePendingStatus(const shared_ptr<FileAsset> &fileAsset, const string &mode)
1650 {
1651     int64_t pendingTime = fileAsset->GetTimePending();
1652     if (pendingTime != 0) {
1653         if (mode == MEDIA_FILEMODE_READONLY) {
1654             MEDIA_ERR_LOG("FileAsset [%{private}s] pending status is %{public}ld and open mode is READ_ONLY",
1655                 fileAsset->GetUri().c_str(), (long) pendingTime);
1656             return E_IS_PENDING_ERROR;
1657         }
1658         string networkId = MediaFileUtils::GetNetworkIdFromUri(fileAsset->GetUri());
1659         if (!networkId.empty()) {
1660             MEDIA_ERR_LOG("Can not open remote [%{private}s] pending file", networkId.c_str());
1661             return E_IS_PENDING_ERROR;
1662         }
1663         if (pendingTime == UNCREATE_FILE_TIMEPENDING) {
1664             int32_t errCode = CreateFileAndSetPending(fileAsset, UNCLOSE_FILE_TIMEPENDING);
1665             return errCode;
1666         }
1667         if (pendingTime == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1668             int32_t errCode = SetPendingTime(fileAsset, UNCLOSE_FILE_TIMEPENDING);
1669             return errCode;
1670         }
1671     }
1672     return E_OK;
1673 }
1674 
CreateDirectoryAndAsset(const string path)1675 static int32_t CreateDirectoryAndAsset(const string path)
1676 {
1677     string dir = MediaFileUtils::GetParentPath(path);
1678     if (!MediaFileUtils::CreateDirectory(dir)) {
1679         MEDIA_ERR_LOG("Create dir failed, dir=%{private}s", dir.c_str());
1680         return E_INVALID_VALUES;
1681     }
1682     int32_t errCode = MediaFileUtils::CreateAsset(path);
1683     if (errCode != E_OK) {
1684         MEDIA_ERR_LOG("Create asset failed, path=%{private}s", path.c_str());
1685         return errCode;
1686     }
1687     return E_OK;
1688 }
1689 
SolveMovingPhotoVideoCreation(const string & imagePath,const string & mode,bool isMovingPhotoVideo)1690 static int32_t SolveMovingPhotoVideoCreation(const string &imagePath, const string &mode, bool isMovingPhotoVideo)
1691 {
1692     if (mode == MEDIA_FILEMODE_READONLY || !isMovingPhotoVideo) {
1693         return E_OK;
1694     }
1695     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(imagePath);
1696     if (MediaFileUtils::IsFileExists(videoPath)) {
1697         return E_OK;
1698     }
1699     int32_t errCode = MediaFileUtils::CreateAsset(videoPath);
1700     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1701         "Create moving photo asset failed, path=%{private}s", videoPath.c_str());
1702     return E_OK;
1703 }
1704 
OpenAsset(const shared_ptr<FileAsset> & fileAsset,const string & mode,MediaLibraryApi api,bool isMovingPhotoVideo,int32_t type)1705 int32_t MediaLibraryAssetOperations::OpenAsset(const shared_ptr<FileAsset> &fileAsset, const string &mode,
1706     MediaLibraryApi api, bool isMovingPhotoVideo, int32_t type)
1707 {
1708     MediaLibraryTracer tracer;
1709     tracer.Start("MediaLibraryAssetOperations::OpenAsset");
1710 
1711     if (fileAsset == nullptr) {
1712         return E_INVALID_VALUES;
1713     }
1714 
1715     string lowerMode = mode;
1716     transform(lowerMode.begin(), lowerMode.end(), lowerMode.begin(), ::tolower);
1717     if (!MediaFileUtils::CheckMode(lowerMode)) {
1718         return E_INVALID_MODE;
1719     }
1720 
1721     string path;
1722     if (api == MediaLibraryApi::API_10) {
1723         int32_t errCode = SolvePendingStatus(fileAsset, mode);
1724         if (errCode != E_OK) {
1725             MEDIA_ERR_LOG("Solve pending status failed, errCode=%{public}d", errCode);
1726             return errCode;
1727         }
1728         path = fileAsset->GetPath();
1729         SolveMovingPhotoVideoCreation(path, mode, isMovingPhotoVideo);
1730     } else {
1731         // If below API10, TIME_PENDING is 0 after asset created, so if file is not exist, create an empty one
1732         if (!MediaFileUtils::IsFileExists(fileAsset->GetPath())) {
1733             MEDIA_INFO_LOG("create empty file for %{public}s, path: %{private}s", fileAsset->GetUri().c_str(),
1734                 fileAsset->GetPath().c_str());
1735             int32_t errCode = CreateDirectoryAndAsset(fileAsset->GetPath());
1736             CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
1737         }
1738         path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
1739     }
1740 
1741     string fileId = MediaFileUtils::GetIdFromUri(fileAsset->GetUri());
1742     MEDIA_DEBUG_LOG("Asset Operation:OpenAsset, type is %{public}d", type);
1743     int32_t fd = OpenFileWithPrivacy(path, lowerMode, fileId, type);
1744     if (fd < 0) {
1745         MEDIA_ERR_LOG(
1746             "open file, userId: %{public}d, uri: %{public}s, path: %{private}s, fd %{public}d, errno %{public}d",
1747             fileAsset->GetUserId(), fileAsset->GetUri().c_str(), fileAsset->GetPath().c_str(), fd, errno);
1748         return E_HAS_FS_ERROR;
1749     }
1750     tracer.Start("AddWatchList");
1751     if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos && !isMovingPhotoVideo) {
1752         auto watch = MediaLibraryInotify::GetInstance();
1753         if (watch != nullptr) {
1754             MEDIA_INFO_LOG("enter inotify, path = %{public}s, fileId = %{public}d",
1755                 DfxUtils::GetSafePath(path).c_str(), fileAsset->GetId());
1756             watch->AddWatchList(path, fileAsset->GetUri(), MediaLibraryApi::API_10);
1757         }
1758     }
1759     tracer.Finish();
1760     return fd;
1761 }
1762 
CloseAsset(const shared_ptr<FileAsset> & fileAsset,bool isCreateThumbSync)1763 int32_t MediaLibraryAssetOperations::CloseAsset(const shared_ptr<FileAsset> &fileAsset, bool isCreateThumbSync)
1764 {
1765     if (fileAsset == nullptr) {
1766         return E_INVALID_VALUES;
1767     }
1768 
1769     // remove inotify event since there is close cmd
1770     auto watch = MediaLibraryInotify::GetInstance();
1771     if (watch != nullptr) {
1772         string uri = fileAsset->GetUri();
1773         watch->RemoveByFileUri(uri, MediaLibraryApi::API_10);
1774         MEDIA_DEBUG_LOG("watch RemoveByFileUri, uri:%{private}s", uri.c_str());
1775     }
1776 
1777     string path = fileAsset->GetPath();
1778     // if pending == 0, scan
1779     // if pending == UNCREATE_FILE_TIMEPENDING, not occur under normal conditions
1780     // if pending == UNCLOSE_FILE_TIMEPENDING, set pending = 0 and scan
1781     // if pending == UNOPEN_FILE_COMPONENT_TIMEPENDING, not allowed to close
1782     // if pending is timestamp, do nothing
1783     if (fileAsset->GetTimePending() == 0 || fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1784         if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1785             ScanFile(path, isCreateThumbSync, false);
1786         } else {
1787             ScanFile(path, isCreateThumbSync, true);
1788         }
1789         return E_OK;
1790     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING ||
1791         fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1792         MEDIA_ERR_LOG("This asset [%{public}d] pending status cannot close", fileAsset->GetId());
1793         return E_IS_PENDING_ERROR;
1794     } else if (fileAsset->GetTimePending() > 0) {
1795         MEDIA_WARN_LOG("This asset [%{public}d] is in pending", fileAsset->GetId());
1796         return E_OK;
1797     } else {
1798         MEDIA_ERR_LOG("This asset [%{public}d] pending status is invalid", fileAsset->GetId());
1799         return E_INVALID_VALUES;
1800     }
1801 }
1802 
OpenHighlightCover(MediaLibraryCommand & cmd,const string & mode)1803 int32_t MediaLibraryAssetOperations::OpenHighlightCover(MediaLibraryCommand &cmd, const string &mode)
1804 {
1805     MediaLibraryTracer tracer;
1806     tracer.Start("MediaLibraryAssetOperations::OpenHighlightCover");
1807     string uriStr = cmd.GetUriStringWithoutSegment();
1808     string path = MediaFileUtils::GetHighlightPath(uriStr);
1809     CHECK_AND_RETURN_RET_LOG(path.length() != 0, E_INVALID_URI,
1810         "Open highlight cover invalid uri : %{public}s", uriStr.c_str());
1811 
1812     shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
1813     fileAsset->SetPath(path);
1814     fileAsset->SetUri(uriStr);
1815     return OpenAsset(fileAsset, mode, cmd.GetApi(), false);
1816 }
1817 
OpenHighlightVideo(MediaLibraryCommand & cmd,const string & mode)1818 int32_t MediaLibraryAssetOperations::OpenHighlightVideo(MediaLibraryCommand &cmd, const string &mode)
1819 {
1820     MediaLibraryTracer tracer;
1821     tracer.Start("MediaLibraryAssetOperations::OpenHighlightVideo");
1822     string uriStr = cmd.GetUriStringWithoutSegment();
1823     string path = MediaFileUtils::GetHighlightVideoPath(uriStr);
1824 
1825     CHECK_AND_RETURN_RET_LOG(path.length() != 0, E_INVALID_URI,
1826         "Open highlight video invalid uri : %{public}s", uriStr.c_str());
1827     shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
1828     fileAsset->SetPath(path);
1829     fileAsset->SetUri(uriStr);
1830     return OpenAsset(fileAsset, mode, cmd.GetApi(), false);
1831 }
1832 
InvalidateThumbnail(const string & fileId,int32_t type)1833 void MediaLibraryAssetOperations::InvalidateThumbnail(const string &fileId, int32_t type)
1834 {
1835     string tableName;
1836     switch (type) {
1837         case MediaType::MEDIA_TYPE_IMAGE:
1838         case MediaType::MEDIA_TYPE_VIDEO: {
1839             tableName = PhotoColumn::PHOTOS_TABLE;
1840             break;
1841         }
1842         case MediaType::MEDIA_TYPE_AUDIO: {
1843             tableName = AudioColumn::AUDIOS_TABLE;
1844             break;
1845         }
1846         default: {
1847             MEDIA_ERR_LOG("Can not match this type %{public}d", type);
1848             return;
1849         }
1850     }
1851     ThumbnailService::GetInstance()->HasInvalidateThumbnail(fileId, tableName);
1852 }
1853 
ScanFile(const string & path,bool isCreateThumbSync,bool isInvalidateThumb,bool isForceScan,int32_t fileId,std::shared_ptr<Media::Picture> resultPicture)1854 void MediaLibraryAssetOperations::ScanFile(const string &path, bool isCreateThumbSync, bool isInvalidateThumb,
1855     bool isForceScan, int32_t fileId, std::shared_ptr<Media::Picture> resultPicture)
1856 {
1857     // Force Scan means medialibrary will scan file without checking E_SCANNED
1858     shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
1859     if (scanAssetCallback == nullptr) {
1860         MEDIA_ERR_LOG("Failed to create scan file callback object");
1861         return;
1862     }
1863     scanAssetCallback->SetOriginalPhotoPicture(resultPicture);
1864     if (isCreateThumbSync) {
1865         scanAssetCallback->SetSync(true);
1866     }
1867     if (!isInvalidateThumb) {
1868         scanAssetCallback->SetIsInvalidateThumb(false);
1869     }
1870 
1871     int ret = MediaScannerManager::GetInstance()->ScanFileSync(path, scanAssetCallback, MediaLibraryApi::API_10,
1872         isForceScan, fileId);
1873     if (ret != 0) {
1874         MEDIA_ERR_LOG("Scan file failed with error: %{public}d", ret);
1875     }
1876 }
1877 
ScanFileWithoutAlbumUpdate(const string & path,bool isCreateThumbSync,bool isInvalidateThumb,bool isForceScan,int32_t fileId,std::shared_ptr<Media::Picture> resultPicture)1878 void MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(const string &path, bool isCreateThumbSync,
1879     bool isInvalidateThumb, bool isForceScan, int32_t fileId, std::shared_ptr<Media::Picture> resultPicture)
1880 {
1881     // Force Scan means medialibrary will scan file without checking E_SCANNED
1882     shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
1883     if (scanAssetCallback == nullptr) {
1884         MEDIA_ERR_LOG("Failed to create scan file callback object");
1885         return;
1886     }
1887     scanAssetCallback->SetOriginalPhotoPicture(resultPicture);
1888     if (isCreateThumbSync) {
1889         scanAssetCallback->SetSync(true);
1890     }
1891     if (!isInvalidateThumb) {
1892         scanAssetCallback->SetIsInvalidateThumb(false);
1893     }
1894 
1895     int ret = MediaScannerManager::GetInstance()->ScanFileSyncWithoutAlbumUpdate(path, scanAssetCallback,
1896         MediaLibraryApi::API_10, isForceScan, fileId);
1897     CHECK_AND_PRINT_LOG(ret == 0, "Scan file failed with error: %{public}d", ret);
1898 }
1899 
GetEditDataDirPath(const string & path)1900 string MediaLibraryAssetOperations::GetEditDataDirPath(const string &path)
1901 {
1902     if (path.length() < ROOT_MEDIA_DIR.length()) {
1903         return "";
1904     }
1905     return MEDIA_EDIT_DATA_DIR + path.substr(ROOT_MEDIA_DIR.length());
1906 }
1907 
GetEditDataSourcePath(const string & path)1908 string MediaLibraryAssetOperations::GetEditDataSourcePath(const string &path)
1909 {
1910     string parentPath = GetEditDataDirPath(path);
1911     if (parentPath.empty()) {
1912         return "";
1913     }
1914     return parentPath + "/source." + MediaFileUtils::GetExtensionFromPath(path);
1915 }
1916 
GetEditDataPath(const string & path)1917 string MediaLibraryAssetOperations::GetEditDataPath(const string &path)
1918 {
1919     string parentPath = GetEditDataDirPath(path);
1920     if (parentPath.empty()) {
1921         return "";
1922     }
1923     return parentPath + "/editdata";
1924 }
1925 
GetEditDataCameraPath(const string & path)1926 string MediaLibraryAssetOperations::GetEditDataCameraPath(const string &path)
1927 {
1928     string parentPath = GetEditDataDirPath(path);
1929     if (parentPath.empty()) {
1930         return "";
1931     }
1932     return parentPath + "/editdata_camera";
1933 }
1934 
GetAssetCacheDir()1935 string MediaLibraryAssetOperations::GetAssetCacheDir()
1936 {
1937     string cacheOwner = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
1938     if (cacheOwner.empty()) {
1939         cacheOwner = "common"; // Create cache file in common dir if there is no bundleName.
1940     }
1941     return MEDIA_CACHE_DIR + cacheOwner;
1942 }
1943 
UpdateAlbumsAndSendNotifyInTrash(AsyncTaskData * data)1944 static void UpdateAlbumsAndSendNotifyInTrash(AsyncTaskData *data)
1945 {
1946     if (data == nullptr) {
1947         return;
1948     }
1949     DeleteNotifyAsyncTaskData* notifyData = static_cast<DeleteNotifyAsyncTaskData*>(data);
1950 
1951     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1952     if (rdbStore == nullptr) {
1953         MEDIA_ERR_LOG("Can not get rdbstore");
1954         return;
1955     }
1956     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, {notifyData->notifyUri});
1957 
1958     auto watch = MediaLibraryNotify::GetInstance();
1959     if (watch == nullptr) {
1960         MEDIA_ERR_LOG("Can not get MediaLibraryNotify");
1961         return;
1962     }
1963     if (notifyData->trashDate > 0) {
1964         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_REMOVE);
1965         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
1966     } else {
1967         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ADD);
1968         watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET);
1969     }
1970 
1971     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
1972     if (trashAlbumId <= 0) {
1973         return;
1974     }
1975     NotifyType type = (notifyData->trashDate > 0) ? NotifyType::NOTIFY_ALBUM_ADD_ASSET :
1976         NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1977     watch->Notify(notifyData->notifyUri, type, trashAlbumId);
1978     vector<int64_t> formIds;
1979     MediaLibraryFormMapOperations::GetFormMapFormId(notifyData->notifyUri, formIds);
1980     if (!formIds.empty()) {
1981         MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
1982     }
1983 }
1984 
SendTrashNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1985 int32_t MediaLibraryAssetOperations::SendTrashNotify(MediaLibraryCommand &cmd, int32_t rowId, const string &extraUri)
1986 {
1987     ValueObject value;
1988     int64_t trashDate = 0;
1989     if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_DATE_TRASHED, value)) {
1990         return E_DO_NOT_NEDD_SEND_NOTIFY;
1991     }
1992 
1993     value.GetLong(trashDate);
1994 
1995     string prefix;
1996     if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
1997         prefix = PhotoColumn::PHOTO_URI_PREFIX;
1998     } else if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_AUDIO) {
1999         prefix = AudioColumn::AUDIO_URI_PREFIX;
2000     } else {
2001         return E_OK;
2002     }
2003 
2004     string notifyUri = MediaFileUtils::GetUriByExtrConditions(prefix, to_string(rowId), extraUri);
2005     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
2006     if (asyncWorker == nullptr) {
2007         MEDIA_ERR_LOG("Can not get asyncWorker");
2008         return E_ERR;
2009     }
2010     DeleteNotifyAsyncTaskData* taskData = new (std::nothrow) DeleteNotifyAsyncTaskData();
2011     if (taskData == nullptr) {
2012         MEDIA_ERR_LOG("Failed to new taskData");
2013         return E_ERR;
2014     }
2015     taskData->notifyUri = notifyUri;
2016     taskData->trashDate = trashDate;
2017     shared_ptr<MediaLibraryAsyncTask> notifyAsyncTask = make_shared<MediaLibraryAsyncTask>(
2018         UpdateAlbumsAndSendNotifyInTrash, taskData);
2019     if (notifyAsyncTask != nullptr) {
2020         asyncWorker->AddTask(notifyAsyncTask, true);
2021     } else {
2022         MEDIA_ERR_LOG("Start UpdateAlbumsAndSendNotifyInTrash failed");
2023     }
2024     return E_OK;
2025 }
2026 
SendFavoriteNotify(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & extraUri)2027 void MediaLibraryAssetOperations::SendFavoriteNotify(MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset,
2028     const string &extraUri)
2029 {
2030     ValueObject value;
2031     int32_t isFavorite = 0;
2032     if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_IS_FAV, value)) {
2033         return;
2034     }
2035     value.GetInt(isFavorite);
2036 
2037     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2038     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
2039     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
2040         rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
2041     CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is nullptr");
2042     if (fileAsset->IsHidden()) {
2043         MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(
2044             rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
2045     }
2046 
2047     auto watch = MediaLibraryNotify::GetInstance();
2048     CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
2049     if (cmd.GetOprnObject() != OperationObject::FILESYSTEM_PHOTO) {
2050         return;
2051     }
2052     int favAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE);
2053     if (favAlbumId <= 0) {
2054         return;
2055     }
2056 
2057     NotifyType type = (isFavorite) ? NotifyType::NOTIFY_ALBUM_ADD_ASSET : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
2058     watch->Notify(
2059         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri),
2060         type, favAlbumId);
2061 }
2062 
SendModifyUserCommentNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)2063 int32_t MediaLibraryAssetOperations::SendModifyUserCommentNotify(MediaLibraryCommand &cmd, int32_t rowId,
2064     const string &extraUri)
2065 {
2066     if (cmd.GetOprnType() != OperationType::SET_USER_COMMENT) {
2067         return E_DO_NOT_NEDD_SEND_NOTIFY;
2068     }
2069 
2070     auto watch = MediaLibraryNotify::GetInstance();
2071     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
2072     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(rowId), extraUri),
2073         NotifyType::NOTIFY_UPDATE);
2074     return E_OK;
2075 }
2076 
GetAlbumIdByPredicates(const string & whereClause,const vector<string> & whereArgs)2077 int32_t MediaLibraryAssetOperations::GetAlbumIdByPredicates(const string &whereClause, const vector<string> &whereArgs)
2078 {
2079     size_t pos = whereClause.find(PhotoColumn::PHOTO_OWNER_ALBUM_ID);
2080     CHECK_AND_RETURN_RET_LOG(pos != string::npos, E_ERR, "Predicates whereClause is invalid");
2081     size_t argsIndex = 0;
2082     for (size_t i = 0; i < pos; ++i) {
2083         if (whereClause[i] == '?') {
2084             argsIndex++;
2085         }
2086     }
2087     if (argsIndex > whereArgs.size() - 1) {
2088         MEDIA_ERR_LOG("whereArgs is invalid");
2089         return E_ERR;
2090     }
2091     auto albumId = whereArgs[argsIndex];
2092     CHECK_AND_RETURN_RET(!MediaLibraryDataManagerUtils::IsNumber(albumId), std::atoi(albumId.c_str()));
2093     return E_ERR;
2094 }
2095 
UpdateOwnerAlbumIdOnMove(MediaLibraryCommand & cmd,int32_t & targetAlbumId,int32_t & oriAlbumId)2096 void MediaLibraryAssetOperations::UpdateOwnerAlbumIdOnMove(MediaLibraryCommand &cmd,
2097     int32_t &targetAlbumId, int32_t &oriAlbumId)
2098 {
2099     ValueObject value;
2100     if (!cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, value)) {
2101         return;
2102     }
2103     value.GetInt(targetAlbumId);
2104     auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
2105     auto whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
2106     oriAlbumId = GetAlbumIdByPredicates(whereClause, whereArgs);
2107     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2108     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
2109 
2110     MediaLibraryRdbUtils::UpdateUserAlbumInternal(
2111         rdbStore, { to_string(targetAlbumId), to_string(oriAlbumId) });
2112     MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
2113         rdbStore, { to_string(targetAlbumId), to_string(oriAlbumId) });
2114     MEDIA_INFO_LOG("Move Assets, ori album id is %{public}d, target album id is %{public}d", oriAlbumId, targetAlbumId);
2115 }
2116 
SetPendingTrue(const shared_ptr<FileAsset> & fileAsset)2117 int32_t MediaLibraryAssetOperations::SetPendingTrue(const shared_ptr<FileAsset> &fileAsset)
2118 {
2119     // time_pending = 0, means file is created, not allowed
2120     // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, create an empty one
2121     // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, set pending time
2122     // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, set pending time
2123     // time_pending is timestamp, update it
2124     int64_t timestamp = MediaFileUtils::UTCTimeSeconds();
2125     if (timestamp <= 0) {
2126         MEDIA_ERR_LOG("Get timestamp failed, timestamp:%{public}ld", (long) timestamp);
2127         return E_INVALID_TIMESTAMP;
2128     }
2129     if (fileAsset->GetTimePending() == 0) {
2130         MEDIA_ERR_LOG("fileAsset time_pending is 0, not allowed");
2131         return E_INVALID_VALUES;
2132     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
2133         int32_t errCode = CreateFileAndSetPending(fileAsset, timestamp);
2134         if (errCode != E_OK) {
2135             MEDIA_ERR_LOG("Create asset failed, id=%{public}d", fileAsset->GetId());
2136             return errCode;
2137         }
2138     } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING ||
2139         fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING ||
2140         fileAsset->GetTimePending() > 0) {
2141         int32_t errCode = SetPendingTime(fileAsset, timestamp);
2142         if (errCode != E_OK) {
2143             MEDIA_ERR_LOG("Set pending time failed, id=%{public}d", fileAsset->GetId());
2144             return errCode;
2145         }
2146     } else {
2147         MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
2148             (long) fileAsset->GetTimePending(), fileAsset->GetId());
2149         return E_INVALID_VALUES;
2150     }
2151 
2152     return E_OK;
2153 }
2154 
SetPendingFalse(const shared_ptr<FileAsset> & fileAsset)2155 int32_t MediaLibraryAssetOperations::SetPendingFalse(const shared_ptr<FileAsset> &fileAsset)
2156 {
2157     // time_pending = 0, only return
2158     // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, not allowed
2159     // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, not allowed
2160     // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, not allowed
2161     // time_pending is timestamp, scan and set pending time = 0
2162     if (fileAsset->GetTimePending() == 0) {
2163         return E_OK;
2164     } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
2165         MEDIA_ERR_LOG("file is not created yet, not allowed, id=%{public}d", fileAsset->GetId());
2166         return E_INVALID_VALUES;
2167     } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
2168         MEDIA_ERR_LOG("file is not close yet, not allowed, id=%{public}d", fileAsset->GetId());
2169         return E_INVALID_VALUES;
2170     } else if (fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
2171         MEDIA_ERR_LOG("file is created but not open, not allowed, id=%{public}d", fileAsset->GetId());
2172         return E_INVALID_VALUES;
2173     } else if (fileAsset->GetTimePending() > 0) {
2174         ScanFile(fileAsset->GetPath(), true, true);
2175     } else {
2176         MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
2177             (long) fileAsset->GetTimePending(), fileAsset->GetId());
2178         return E_INVALID_VALUES;
2179     }
2180     return E_OK;
2181 }
2182 
SetPendingStatus(MediaLibraryCommand & cmd)2183 int32_t MediaLibraryAssetOperations::SetPendingStatus(MediaLibraryCommand &cmd)
2184 {
2185     int32_t pendingStatus = 0;
2186     if (!GetInt32FromValuesBucket(cmd.GetValueBucket(), MediaColumn::MEDIA_TIME_PENDING, pendingStatus)) {
2187         return E_INVALID_VALUES;
2188     }
2189 
2190     vector<string> columns = {
2191         MediaColumn::MEDIA_ID,
2192         MediaColumn::MEDIA_FILE_PATH,
2193         MediaColumn::MEDIA_TYPE,
2194         MediaColumn::MEDIA_TIME_PENDING
2195     };
2196     auto fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()), cmd.GetOprnObject(), columns);
2197     if (fileAsset == nullptr) {
2198         return E_INVALID_VALUES;
2199     }
2200     if (pendingStatus == 1) {
2201         return SetPendingTrue(fileAsset);
2202     } else if (pendingStatus == 0) {
2203         return SetPendingFalse(fileAsset);
2204     } else {
2205         MEDIA_ERR_LOG("pendingStatus is invalid, pendingStatus:%{public}d", pendingStatus);
2206         return E_INVALID_VALUES;
2207     }
2208 }
2209 
ConvertMediaPathFromCloudPath(const string & path)2210 static string ConvertMediaPathFromCloudPath(const string &path)
2211 {
2212     // if input path is /storage/cloud/xxx, return /storage/media/local/xxx
2213     string mediaPath = "/storage/media/local/";
2214     string cloudPath = "/storage/cloud/";
2215     string newPath = path;
2216     if (newPath.find(cloudPath) != string::npos) {
2217         newPath.replace(newPath.find(cloudPath), cloudPath.length(), mediaPath);
2218     }
2219     return newPath;
2220 }
2221 
GrantUriPermission(const string & uri,const string & bundleName,const string & path,bool isMovingPhoto)2222 int32_t MediaLibraryAssetOperations::GrantUriPermission(const string &uri, const string &bundleName,
2223     const string &path, bool isMovingPhoto)
2224 {
2225     if (uri.empty() || path.empty()) {
2226         MEDIA_ERR_LOG("uri or path is empty, uri:%{private}s, path:%{private}s", uri.c_str(), path.c_str());
2227         return E_INVALID_VALUES;
2228     }
2229     if (bundleName.empty()) {
2230         MEDIA_WARN_LOG("bundleName is empty, bundleName:%{private}s", bundleName.c_str());
2231         return E_OK;
2232     }
2233     if (!MediaFileUtils::CreateFile(path)) {
2234         MEDIA_ERR_LOG("Can not create file, path: %{private}s, errno: %{public}d", path.c_str(), errno);
2235         return E_HAS_FS_ERROR;
2236     }
2237 
2238     if (isMovingPhoto && !MediaFileUtils::CreateFile(MediaFileUtils::GetMovingPhotoVideoPath(path))) {
2239         MEDIA_ERR_LOG("Failed to create video of moving photo, errno: %{public}d", errno);
2240         return E_HAS_FS_ERROR;
2241     }
2242 
2243     return E_OK;
2244 }
2245 
GetInt32FromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,int32_t & value)2246 bool MediaLibraryAssetOperations::GetInt32FromValuesBucket(const NativeRdb::ValuesBucket &values,
2247     const std::string &column, int32_t &value)
2248 {
2249     ValueObject valueObject;
2250     if (values.GetObject(column, valueObject)) {
2251         valueObject.GetInt(value);
2252     } else {
2253         return false;
2254     }
2255     return true;
2256 }
2257 
CreateExtUriForV10Asset(FileAsset & fileAsset)2258 std::string MediaLibraryAssetOperations::CreateExtUriForV10Asset(FileAsset &fileAsset)
2259 {
2260     const std::string &filePath = fileAsset.GetPath();
2261     const std::string &displayName = fileAsset.GetDisplayName();
2262     auto mediaType = fileAsset.GetMediaType();
2263     if (filePath.empty() || displayName.empty() || mediaType < 0) {
2264         MEDIA_ERR_LOG("param invalid, filePath %{private}s or displayName %{private}s invalid failed.",
2265             filePath.c_str(), displayName.c_str());
2266         return "";
2267     }
2268 
2269     string extrUri = MediaFileUtils::GetExtraUri(displayName, filePath);
2270     return MediaFileUtils::GetUriByExtrConditions(ML_FILE_URI_PREFIX + MediaFileUri::GetMediaTypeUri(mediaType,
2271         MEDIA_API_VERSION_V10) + "/", to_string(fileAsset.GetId()), extrUri);
2272 }
2273 
GetStringFromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,string & value)2274 bool MediaLibraryAssetOperations::GetStringFromValuesBucket(const NativeRdb::ValuesBucket &values,
2275     const std::string &column, string &value)
2276 {
2277     ValueObject valueObject;
2278     if (values.GetObject(column, valueObject)) {
2279         valueObject.GetString(value);
2280     } else {
2281         return false;
2282     }
2283     return true;
2284 }
2285 
CreateAssetUniqueId(int32_t type,std::shared_ptr<TransactionOperations> trans)2286 int32_t MediaLibraryAssetOperations::CreateAssetUniqueId(int32_t type,
2287     std::shared_ptr<TransactionOperations> trans)
2288 {
2289     string typeString;
2290     switch (type) {
2291         case MediaType::MEDIA_TYPE_IMAGE:
2292             typeString += IMAGE_ASSET_TYPE;
2293             break;
2294         case MediaType::MEDIA_TYPE_VIDEO:
2295             typeString += VIDEO_ASSET_TYPE;
2296             break;
2297         case MediaType::MEDIA_TYPE_AUDIO:
2298             typeString += AUDIO_ASSET_TYPE;
2299             break;
2300         default:
2301             MEDIA_ERR_LOG("This type %{public}d can not get unique id", type);
2302             return E_INVALID_VALUES;
2303     }
2304 
2305     const string updateSql = "UPDATE " + ASSET_UNIQUE_NUMBER_TABLE + " SET " + UNIQUE_NUMBER +
2306         "=" + UNIQUE_NUMBER + "+1" " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2307     const string querySql = "SELECT " + UNIQUE_NUMBER + " FROM " + ASSET_UNIQUE_NUMBER_TABLE +
2308         " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2309 
2310     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2311     if (rdbStore == nullptr) {
2312         return E_HAS_DB_ERROR;
2313     }
2314     lock_guard<mutex> lock(g_uniqueNumberLock);
2315     int32_t errCode;
2316     if (trans == nullptr) {
2317         errCode = rdbStore->ExecuteSql(updateSql);
2318     } else {
2319         errCode = trans->ExecuteSql(updateSql);
2320     }
2321     if (errCode < 0) {
2322         MEDIA_ERR_LOG("execute update unique number failed, ret=%{public}d", errCode);
2323         return errCode;
2324     }
2325 
2326     auto resultSet = rdbStore->QuerySql(querySql);
2327     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2328         return E_HAS_DB_ERROR;
2329     }
2330     return GetInt32Val(UNIQUE_NUMBER, resultSet);
2331 }
2332 
CreateAssetUniqueIds(int32_t type,int32_t num,int32_t & startUniqueNumber)2333 int32_t MediaLibraryAssetOperations::CreateAssetUniqueIds(int32_t type, int32_t num, int32_t &startUniqueNumber)
2334 {
2335     if (num == 0) {
2336         return E_OK;
2337     }
2338     string typeString;
2339     switch (type) {
2340         case MediaType::MEDIA_TYPE_IMAGE:
2341             typeString = IMAGE_ASSET_TYPE;
2342             break;
2343         case MediaType::MEDIA_TYPE_VIDEO:
2344             typeString = VIDEO_ASSET_TYPE;
2345             break;
2346         case MediaType::MEDIA_TYPE_AUDIO:
2347             typeString = AUDIO_ASSET_TYPE;
2348             break;
2349         default:
2350             MEDIA_ERR_LOG("This type %{public}d can not get unique id", type);
2351             return E_INVALID_VALUES;
2352     }
2353     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2354     if (rdbStore == nullptr) {
2355         return E_HAS_DB_ERROR;
2356     }
2357     const string updateSql = "UPDATE " + ASSET_UNIQUE_NUMBER_TABLE + " SET " + UNIQUE_NUMBER +
2358         "=" + UNIQUE_NUMBER + "+" + to_string(num) + " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2359     const string querySql = "SELECT " + UNIQUE_NUMBER + " FROM " + ASSET_UNIQUE_NUMBER_TABLE +
2360         " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2361     lock_guard<mutex> lock(g_uniqueNumberLock);
2362     int32_t errCode = rdbStore->ExecuteSql(updateSql);
2363     if (errCode < 0) {
2364         MEDIA_ERR_LOG("CreateAssetUniqueIds ExecuteSql err, ret=%{public}d", errCode);
2365         return errCode;
2366     }
2367     auto resultSet = rdbStore->QuerySql(querySql);
2368     if (resultSet == nullptr) {
2369         MEDIA_ERR_LOG("CreateAssetUniqueIds resultSet is null");
2370         return E_HAS_DB_ERROR;
2371     }
2372     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2373         MEDIA_ERR_LOG("CreateAssetUniqueIds first row empty");
2374         resultSet->Close();
2375         return E_HAS_DB_ERROR;
2376     }
2377     int32_t endUniqueNumber = GetInt32Val(UNIQUE_NUMBER, resultSet);
2378     resultSet->Close();
2379     startUniqueNumber = endUniqueNumber - num + 1;
2380     MEDIA_INFO_LOG("CreateAssetUniqueIds type: %{public}d, num: %{public}d, startUniqueNumber: %{public}d",
2381         type, num, startUniqueNumber);
2382     return E_OK;
2383 }
2384 
CreateAssetRealName(int32_t fileId,int32_t mediaType,const string & extension,string & name)2385 int32_t MediaLibraryAssetOperations::CreateAssetRealName(int32_t fileId, int32_t mediaType,
2386     const string &extension, string &name)
2387 {
2388     string fileNumStr = to_string(fileId);
2389     if (fileId <= ASSET_MAX_COMPLEMENT_ID) {
2390         size_t fileIdLen = fileNumStr.length();
2391         fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
2392     }
2393 
2394     string mediaTypeStr;
2395     switch (mediaType) {
2396         case MediaType::MEDIA_TYPE_IMAGE:
2397             mediaTypeStr = DEFAULT_IMAGE_NAME;
2398             break;
2399         case MediaType::MEDIA_TYPE_VIDEO:
2400             mediaTypeStr = DEFAULT_VIDEO_NAME;
2401             break;
2402         case MediaType::MEDIA_TYPE_AUDIO:
2403             mediaTypeStr = DEFAULT_AUDIO_NAME;
2404             break;
2405         default:
2406             MEDIA_ERR_LOG("This mediatype %{public}d can not get real name", mediaType);
2407             return E_INVALID_VALUES;
2408     }
2409 
2410     static const int32_t CONFLICT_TIME = 100;
2411     name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds() + CONFLICT_TIME) + "_" +
2412         fileNumStr + "." + extension;
2413     return E_OK;
2414 }
2415 
PrepareAssetDir(const string & dirPath)2416 static inline int32_t PrepareAssetDir(const string &dirPath)
2417 {
2418     CHECK_AND_RETURN_RET(!dirPath.empty(), E_INVALID_PATH);
2419     if (!MediaFileUtils::IsFileExists(dirPath)) {
2420         bool ret = MediaFileUtils::CreateDirectory(dirPath);
2421         CHECK_AND_RETURN_RET_LOG(ret, E_CHECK_DIR_FAIL, "Create Dir Failed! dirPath=%{private}s",
2422             dirPath.c_str());
2423     }
2424     return E_OK;
2425 }
2426 
CreateAssetPathById(int32_t fileId,int32_t mediaType,const string & extension,string & filePath)2427 int32_t MediaLibraryAssetOperations::CreateAssetPathById(int32_t fileId, int32_t mediaType,
2428     const string &extension, string &filePath)
2429 {
2430     string mediaDirPath;
2431     GetAssetRootDir(mediaType, mediaDirPath);
2432     if (mediaDirPath.empty()) {
2433         return E_INVALID_VALUES;
2434     }
2435 
2436     int32_t bucketNum = 0;
2437     int32_t errCode = MediaFileUri::CreateAssetBucket(fileId, bucketNum);
2438     if (errCode != E_OK) {
2439         return errCode;
2440     }
2441 
2442     string realName;
2443     errCode = CreateAssetRealName(fileId, mediaType, extension, realName);
2444     if (errCode != E_OK) {
2445         return errCode;
2446     }
2447 
2448     string dirPath = ROOT_MEDIA_DIR + mediaDirPath + to_string(bucketNum);
2449     errCode = PrepareAssetDir(dirPath);
2450     if (errCode != E_OK) {
2451         return errCode;
2452     }
2453 
2454     filePath = dirPath + "/" + realName;
2455     return E_OK;
2456 }
2457 
2458 const std::unordered_map<std::string, std::vector<VerifyFunction>>
2459     AssetInputParamVerification::UPDATE_VERIFY_PARAM_MAP = {
2460     { MediaColumn::MEDIA_ID, { Forbidden } },
2461     { MediaColumn::MEDIA_FILE_PATH, { Forbidden } },
2462     { MediaColumn::MEDIA_SIZE, { Forbidden } },
2463     { MediaColumn::MEDIA_TITLE, { IsStringNotNull } },
2464     { MediaColumn::MEDIA_NAME, { IsStringNotNull } },
2465     { MediaColumn::MEDIA_TYPE, { Forbidden } },
2466     { MediaColumn::MEDIA_MIME_TYPE, { Forbidden } },
2467     { MediaColumn::MEDIA_OWNER_PACKAGE, { Forbidden } },
2468     { MediaColumn::MEDIA_OWNER_APPID, { Forbidden } },
2469     { MediaColumn::MEDIA_PACKAGE_NAME, { Forbidden } },
2470     { MediaColumn::MEDIA_DEVICE_NAME, { Forbidden } },
2471     { MediaColumn::MEDIA_DATE_MODIFIED, { Forbidden } },
2472     { MediaColumn::MEDIA_DATE_ADDED, { Forbidden } },
2473     { MediaColumn::MEDIA_DATE_TAKEN, { Forbidden } },
2474     { MediaColumn::MEDIA_DURATION, { Forbidden } },
2475     { MediaColumn::MEDIA_TIME_PENDING, { IsInt64, IsUniqueValue } },
2476     { MediaColumn::MEDIA_IS_FAV, { IsBool, IsUniqueValue } },
2477     { MediaColumn::MEDIA_DATE_TRASHED, { IsInt64, IsUniqueValue } },
2478     { MediaColumn::MEDIA_DATE_DELETED, { IsInt64, IsUniqueValue } },
2479     { MediaColumn::MEDIA_HIDDEN, { IsBool, IsUniqueValue } },
2480     { MediaColumn::MEDIA_PARENT_ID, { IsInt64, IsBelowApi9 } },
2481     { MediaColumn::MEDIA_RELATIVE_PATH, { IsString, IsBelowApi9 } },
2482     { MediaColumn::MEDIA_VIRTURL_PATH, { Forbidden } },
2483     { PhotoColumn::PHOTO_ORIENTATION, { IsInt64 } },
2484     { PhotoColumn::PHOTO_LATITUDE, { Forbidden } },
2485     { PhotoColumn::PHOTO_LONGITUDE, { Forbidden } },
2486     { PhotoColumn::PHOTO_HEIGHT, { Forbidden } },
2487     { PhotoColumn::PHOTO_WIDTH, { Forbidden } },
2488     { PhotoColumn::PHOTO_LCD_VISIT_TIME, { IsInt64 } },
2489     { PhotoColumn::PHOTO_EDIT_TIME, { IsInt64 } },
2490     { AudioColumn::AUDIO_ALBUM, { Forbidden } },
2491     { AudioColumn::AUDIO_ARTIST, { Forbidden } },
2492     { PhotoColumn::CAMERA_SHOT_KEY, { IsString } },
2493     { PhotoColumn::PHOTO_USER_COMMENT, { IsString } },
2494     { PhotoColumn::PHOTO_ID, { IsString } },
2495     { PhotoColumn::PHOTO_QUALITY, { IsInt32 } },
2496     { PhotoColumn::PHOTO_FIRST_VISIT_TIME, { IsInt64 } },
2497     { PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, { IsInt32 } },
2498     { PhotoColumn::PHOTO_SUBTYPE, { IsInt32 } },
2499     { PhotoColumn::MOVING_PHOTO_EFFECT_MODE, { IsInt32 } },
2500     { PhotoColumn::PHOTO_COVER_POSITION, { IsInt64 } },
2501     { PhotoColumn::PHOTO_IS_TEMP, { IsBool } },
2502     { PhotoColumn::PHOTO_DIRTY, { IsInt32 } },
2503     { PhotoColumn::PHOTO_DETAIL_TIME, { IsStringNotNull } },
2504     { PhotoColumn::PHOTO_OWNER_ALBUM_ID, { IsInt32 } },
2505     { PhotoColumn::PHOTO_CE_AVAILABLE, { IsInt32 } },
2506     { PhotoColumn::SUPPORTED_WATERMARK_TYPE, { IsInt32 } },
2507     { PhotoColumn::PHOTO_IS_AUTO, { IsInt32 } },
2508     { PhotoColumn::PHOTO_IS_RECENT_SHOW, { IsBool, IsUniqueValue } },
2509 };
2510 
CheckParamForUpdate(MediaLibraryCommand & cmd)2511 bool AssetInputParamVerification::CheckParamForUpdate(MediaLibraryCommand &cmd)
2512 {
2513     ValuesBucket &values = cmd.GetValueBucket();
2514     map<string, ValueObject> valuesMap;
2515     values.GetAll(valuesMap);
2516     for (auto &iter : valuesMap) {
2517         if (UPDATE_VERIFY_PARAM_MAP.find(iter.first) == UPDATE_VERIFY_PARAM_MAP.end()) {
2518             MEDIA_ERR_LOG("param [%{private}s] is not allowed", iter.first.c_str());
2519             return false;
2520         }
2521         for (auto &verifyFunc : UPDATE_VERIFY_PARAM_MAP.at(iter.first)) {
2522             if (!verifyFunc(iter.second, cmd)) {
2523                 MEDIA_ERR_LOG("verify param [%{private}s] failed", iter.first.c_str());
2524                 return false;
2525             }
2526         }
2527     }
2528     return true;
2529 }
2530 
Forbidden(ValueObject & value,MediaLibraryCommand & cmd)2531 bool AssetInputParamVerification::Forbidden(ValueObject &value, MediaLibraryCommand &cmd)
2532 {
2533     return false;
2534 }
2535 
IsInt32(ValueObject & value,MediaLibraryCommand & cmd)2536 bool AssetInputParamVerification::IsInt32(ValueObject &value, MediaLibraryCommand &cmd)
2537 {
2538     if (value.GetType() == ValueObjectType::TYPE_INT) {
2539         return true;
2540     }
2541     return false;
2542 }
2543 
IsInt64(ValueObject & value,MediaLibraryCommand & cmd)2544 bool AssetInputParamVerification::IsInt64(ValueObject &value, MediaLibraryCommand &cmd)
2545 {
2546     if (value.GetType() == ValueObjectType::TYPE_INT) {
2547         return true;
2548     }
2549     return false;
2550 }
2551 
IsBool(ValueObject & value,MediaLibraryCommand & cmd)2552 bool AssetInputParamVerification::IsBool(ValueObject &value, MediaLibraryCommand &cmd)
2553 {
2554     if (value.GetType() == ValueObjectType::TYPE_BOOL) {
2555         return true;
2556     }
2557     if (value.GetType() == ValueObjectType::TYPE_INT) {
2558         int32_t ret;
2559         value.GetInt(ret);
2560         if (ret == 0 || ret == 1) {
2561             return true;
2562         }
2563     }
2564     return false;
2565 }
2566 
IsString(ValueObject & value,MediaLibraryCommand & cmd)2567 bool AssetInputParamVerification::IsString(ValueObject &value, MediaLibraryCommand &cmd)
2568 {
2569     CHECK_AND_RETURN_RET(value.GetType() != ValueObjectType::TYPE_STRING, true);
2570     return false;
2571 }
2572 
IsDouble(ValueObject & value,MediaLibraryCommand & cmd)2573 bool AssetInputParamVerification::IsDouble(ValueObject &value, MediaLibraryCommand &cmd)
2574 {
2575     CHECK_AND_RETURN_RET(value.GetType() != ValueObjectType::TYPE_DOUBLE, true);
2576     return false;
2577 }
2578 
IsBelowApi9(ValueObject & value,MediaLibraryCommand & cmd)2579 bool AssetInputParamVerification::IsBelowApi9(ValueObject &value, MediaLibraryCommand &cmd)
2580 {
2581     CHECK_AND_RETURN_RET(cmd.GetApi() != MediaLibraryApi::API_OLD, true);
2582     return false;
2583 }
2584 
IsStringNotNull(ValueObject & value,MediaLibraryCommand & cmd)2585 bool AssetInputParamVerification::IsStringNotNull(ValueObject &value, MediaLibraryCommand &cmd)
2586 {
2587     if (value.GetType() != ValueObjectType::TYPE_STRING) {
2588         return false;
2589     }
2590     string str;
2591     value.GetString(str);
2592     if (str.empty()) {
2593         return false;
2594     }
2595     return true;
2596 }
2597 
IsUniqueValue(ValueObject & value,MediaLibraryCommand & cmd)2598 bool AssetInputParamVerification::IsUniqueValue(ValueObject &value, MediaLibraryCommand &cmd)
2599 {
2600     // whether this is the unique value in ValuesBucket
2601     map<string, ValueObject> valuesMap;
2602     cmd.GetValueBucket().GetAll(valuesMap);
2603     if (valuesMap.size() != 1) {
2604         return false;
2605     }
2606     return true;
2607 }
2608 
CreateThumbnailFileScaned(const string & uri,const string & path,bool isSync,std::shared_ptr<Media::Picture> originalPhotoPicture)2609 static void CreateThumbnailFileScaned(const string &uri, const string &path, bool isSync,
2610     std::shared_ptr<Media::Picture> originalPhotoPicture)
2611 {
2612     if (ThumbnailService::GetInstance() == nullptr) {
2613         return;
2614     }
2615     CHECK_AND_RETURN_LOG(!uri.empty(), "Uri is empty");
2616     int32_t err = 0;
2617     if (originalPhotoPicture != nullptr) {
2618         err = ThumbnailService::GetInstance()->CreateThumbnailFileScanedWithPicture(
2619             uri, path, originalPhotoPicture, isSync);
2620     } else {
2621         err = ThumbnailService::GetInstance()->CreateThumbnailFileScaned(uri, path, isSync);
2622     }
2623     CHECK_AND_RETURN_LOG(err == E_SUCCESS, "ThumbnailService CreateThumbnailFileScaned failed : %{public}d", err);
2624 }
2625 
OnScanFinished(const int32_t status,const string & uri,const string & path)2626 int32_t MediaLibraryAssetOperations::ScanAssetCallback::OnScanFinished(const int32_t status,
2627     const string &uri, const string &path)
2628 {
2629     if (status == E_SCANNED) {
2630         MEDIA_DEBUG_LOG("Asset is scannned");
2631         return E_OK;
2632     } else if (status != E_OK) {
2633         MEDIA_ERR_LOG("Scan is failed, status = %{public}d, skip create thumbnail", status);
2634         return status;
2635     }
2636 
2637     string fileId = MediaFileUtils::GetIdFromUri(uri);
2638     int32_t type = MediaFileUtils::GetMediaType(path);
2639     if (this->isInvalidateThumb && PhotoFileUtils::IsThumbnailExists(path) &&
2640         !PhotoFileUtils::IsThumbnailLatest(path)) {
2641         InvalidateThumbnail(fileId, type);
2642     }
2643     CreateThumbnailFileScaned(uri, path, this->isCreateThumbSync, originalPhotoPicture);
2644     MediaFileUtils::DeleteFile(MovingPhotoFileUtils::GetLivePhotoCachePath(path));
2645 
2646 #ifdef META_RECOVERY_SUPPORT
2647     int32_t id;
2648     if (StrToInt(fileId, id)) {
2649         MediaLibraryMetaRecovery::GetInstance().WriteSingleMetaDataById(id);
2650     }
2651 #endif
2652 
2653     return E_OK;
2654 }
2655 
TaskDataFileProccess(DeleteFilesTask * taskData)2656 static void TaskDataFileProccess(DeleteFilesTask *taskData)
2657 {
2658     for (size_t i = 0; i < taskData->paths_.size(); i++) {
2659         string filePath = taskData->paths_[i];
2660         string fileId = i < taskData->ids_.size() ? taskData->ids_[i] : "";
2661         MEDIA_INFO_LOG("Delete file id: %{public}s, path: %{public}s", fileId.c_str(), filePath.c_str());
2662         if (!MediaFileUtils::DeleteFile(filePath) && (errno != ENOENT)) {
2663             MEDIA_WARN_LOG("Failed to delete file, errno: %{public}d, path: %{private}s", errno, filePath.c_str());
2664         }
2665 #ifdef META_RECOVERY_SUPPORT
2666         MediaLibraryMetaRecovery::DeleteMetaDataByPath(filePath);
2667 
2668 #endif
2669         if (taskData->subTypes_[i] == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2670             // delete video file of moving photo
2671             string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(filePath);
2672             if (!MediaFileUtils::DeleteFile(videoPath) && (errno != ENOENT)) {
2673                 MEDIA_WARN_LOG("Failed to delete video file, errno: %{public}d, path: %{private}s", errno,
2674                     videoPath.c_str());
2675             }
2676             string livePhotoPath = MovingPhotoFileUtils::GetLivePhotoCachePath(filePath);
2677             if (MediaFileUtils::IsFileExists(livePhotoPath) && !MediaFileUtils::DeleteFile(livePhotoPath)) {
2678                 MEDIA_WARN_LOG("Failed to delete cache live photo, errno: %{public}d, path: %{private}s", errno,
2679                     livePhotoPath.c_str());
2680             }
2681         }
2682     }
2683     for (size_t i = 0; i < taskData->ids_.size(); i++) {
2684         ThumbnailService::GetInstance()->HasInvalidateThumbnail(
2685             taskData->ids_[i], taskData->table_, taskData->paths_[i], taskData->dateTakens_[i]);
2686     }
2687     if (taskData->table_ == PhotoColumn::PHOTOS_TABLE) {
2688         for (const auto &path : taskData->paths_) {
2689             MediaLibraryPhotoOperations::DeleteRevertMessage(path);
2690         }
2691     }
2692 }
2693 
DeleteFiles(AsyncTaskData * data)2694 static void DeleteFiles(AsyncTaskData *data)
2695 {
2696     MediaLibraryTracer tracer;
2697     tracer.Start("DeleteFiles");
2698     if (data == nullptr) {
2699         return;
2700     }
2701     auto *taskData = static_cast<DeleteFilesTask *>(data);
2702     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2703     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
2704     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
2705         rdbStore, { to_string(PhotoAlbumSubType::TRASH) });
2706     MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(
2707         rdbStore, { to_string(PhotoAlbumSubType::TRASH) });
2708 
2709     DfxManager::GetInstance()->HandleDeleteBehavior(DfxType::ALBUM_DELETE_ASSETS, taskData->deleteRows_,
2710         taskData->notifyUris_, taskData->bundleName_);
2711     auto watch = MediaLibraryNotify::GetInstance();
2712     CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
2713     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
2714     if (trashAlbumId <= 0) {
2715         MEDIA_WARN_LOG("Failed to get trash album id: %{public}d", trashAlbumId);
2716         return;
2717     }
2718     size_t uriSize = taskData->notifyUris_.size() > taskData->isTemps_.size() ? taskData->isTemps_.size() :
2719         taskData->notifyUris_.size();
2720     for (size_t index = 0; index < uriSize; index++) {
2721         if (taskData->isTemps_[index]) {
2722             continue;
2723         }
2724         watch->Notify(MediaFileUtils::Encode(taskData->notifyUris_[index]), NotifyType::NOTIFY_ALBUM_REMOVE_ASSET,
2725             trashAlbumId);
2726     }
2727     TaskDataFileProccess(taskData);
2728 }
2729 
HandleAudiosResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,DeletedFilesParams & filesParams)2730 void HandleAudiosResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet, DeletedFilesParams &filesParams)
2731 {
2732     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2733         filesParams.ids.push_back(
2734             to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))));
2735         filesParams.paths.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH,
2736             resultSet, TYPE_STRING)));
2737         filesParams.dateTakens.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DATE_TAKEN,
2738             resultSet, TYPE_STRING)));
2739         filesParams.subTypes.push_back(static_cast<int32_t>(PhotoSubType::DEFAULT));
2740     }
2741 }
2742 
HandlePhotosResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,DeletedFilesParams & filesParams)2743 void HandlePhotosResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet, DeletedFilesParams &filesParams)
2744 {
2745     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2746         filesParams.ids.push_back(
2747             to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))));
2748         filesParams.paths.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH,
2749             resultSet, TYPE_STRING)));
2750         filesParams.dateTakens.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DATE_TAKEN,
2751             resultSet, TYPE_STRING)));
2752         filesParams.subTypes.push_back(
2753             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_SUBTYPE, resultSet, TYPE_INT32)));
2754         filesParams.isTemps.push_back(
2755             get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_IS_TEMP, resultSet, TYPE_INT32)));
2756     }
2757 }
2758 
GetIdsAndPaths(const AbsRdbPredicates & predicates,DeletedFilesParams & filesParams)2759 int32_t GetIdsAndPaths(const AbsRdbPredicates &predicates, DeletedFilesParams &filesParams)
2760 {
2761     vector<string> columns = {
2762         MediaColumn::MEDIA_ID,
2763         MediaColumn::MEDIA_FILE_PATH,
2764         MediaColumn::MEDIA_DATE_TAKEN,
2765         PhotoColumn::PHOTO_IS_TEMP
2766     };
2767 
2768     if (predicates.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
2769         columns.push_back(PhotoColumn::PHOTO_SUBTYPE);
2770     }
2771 
2772     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2773     if (resultSet == nullptr) {
2774         return E_HAS_DB_ERROR;
2775     }
2776 
2777     if (predicates.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
2778         HandlePhotosResultSet(resultSet, filesParams);
2779     } else if (predicates.GetTableName() == AudioColumn::AUDIOS_TABLE) {
2780         HandleAudiosResultSet(resultSet, filesParams);
2781     } else {
2782         MEDIA_WARN_LOG("Invalid table name.");
2783     }
2784     return E_OK;
2785 }
2786 
GetFileAssetsFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & fileColumns,vector<shared_ptr<FileAsset>> & fileAssets)2787 static int32_t GetFileAssetsFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
2788     const vector<string> &fileColumns, vector<shared_ptr<FileAsset>> &fileAssets)
2789 {
2790     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "The provided resultSet is nullptr");
2791     int32_t fileCount = 0;
2792     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(fileCount) == NativeRdb::E_OK, E_HAS_DB_ERROR,
2793         "Cannot get fileCount of resultset");
2794     CHECK_AND_RETURN_RET_LOG(fileCount > 0, E_HAS_DB_ERROR, "ResultSet fileCount is %{public}d", fileCount);
2795 
2796     fileAssets.reserve(fileCount);
2797     for (int32_t i = 0; i < fileCount; i++) {
2798         CHECK_AND_RETURN_RET_LOG(
2799             resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
2800         auto fileAsset = FetchFileAssetFromResultSet(resultSet, fileColumns);
2801         CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Failed to fetch fileAsset from resultSet");
2802         fileAssets.push_back(fileAsset);
2803     }
2804     resultSet->Close();
2805     return E_OK;
2806 }
2807 
GetAssetSize(const std::string & extraPath)2808 static int64_t GetAssetSize(const std::string &extraPath)
2809 {
2810     MEDIA_DEBUG_LOG("GetAssetSize start.");
2811     string absExtraPath;
2812     CHECK_AND_RETURN_RET_LOG(PathToRealPath(extraPath, absExtraPath), static_cast<int64_t>(E_ERR),
2813         "file is not real path: %{private}s", extraPath.c_str());
2814 
2815     UniqueFd fd(open(absExtraPath.c_str(), O_RDONLY));
2816     CHECK_AND_RETURN_RET_LOG(fd.Get() != E_ERR, static_cast<int64_t>(E_ERR),
2817         "failed to open extra file");
2818 
2819     struct stat st;
2820     CHECK_AND_RETURN_RET_LOG(fstat(fd.Get(), &st) == E_OK, static_cast<int64_t>(E_ERR),
2821         "failed to get file size");
2822     off_t fileSize = st.st_size;
2823     return static_cast<int64_t>(fileSize);
2824 }
2825 
PushMovingPhotoExternalPath(const std::string & path,const std::string & logTarget,vector<string> & attachment)2826 static void PushMovingPhotoExternalPath(const std::string &path, const std::string &logTarget,
2827     vector<string> &attachment)
2828 {
2829     if (path.empty()) {
2830         MEDIA_WARN_LOG("%{public}s is invalid.", logTarget.c_str());
2831         return;
2832     }
2833     attachment.push_back(path);
2834 }
2835 
GetMovingPhotoExternalInfo(ExternalInfo & exInfo,vector<string> & attachment)2836 static void GetMovingPhotoExternalInfo(ExternalInfo &exInfo, vector<string> &attachment)
2837 {
2838     MEDIA_DEBUG_LOG("GetMovingPhotoExternalInfo start.");
2839     if (!MovingPhotoFileUtils::IsMovingPhoto(exInfo.subType, exInfo.effectMode, exInfo.originalSubType)) {
2840         return;
2841     }
2842     exInfo.videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(exInfo.path);
2843     exInfo.extraPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(exInfo.path);
2844     exInfo.photoImagePath = MovingPhotoFileUtils::GetSourceMovingPhotoImagePath(exInfo.path);
2845     exInfo.photoVideoPath = MovingPhotoFileUtils::GetSourceMovingPhotoVideoPath(exInfo.path);
2846     exInfo.cachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(exInfo.path);
2847     PushMovingPhotoExternalPath(exInfo.videoPath, "videoPath", attachment);
2848     PushMovingPhotoExternalPath(exInfo.extraPath, "extraPath", attachment);
2849     PushMovingPhotoExternalPath(exInfo.photoImagePath, "photoImagePath", attachment);
2850     PushMovingPhotoExternalPath(exInfo.photoVideoPath, "photoVideoPath", attachment);
2851     PushMovingPhotoExternalPath(exInfo.cachePath, "cachePath", attachment);
2852     MEDIA_INFO_LOG("videoPath is %{public}s, extraPath is %{public}s, photoImagePath is %{public}s, \
2853         photoVideoPath is %{public}s, cachePath is %{public}s.", DfxUtils::GetSafePath(exInfo.videoPath).c_str(),
2854         DfxUtils::GetSafePath(exInfo.extraPath).c_str(), DfxUtils::GetSafePath(exInfo.photoImagePath).c_str(),
2855         DfxUtils::GetSafePath(exInfo.photoVideoPath).c_str(), DfxUtils::GetSafePath(exInfo.cachePath).c_str());
2856     exInfo.sizeMp4 = GetAssetSize(exInfo.videoPath);
2857     exInfo.sizeExtra = GetAssetSize(exInfo.extraPath);
2858     if (exInfo.sizeMp4 <= INVALID_SIZE) {
2859         MEDIA_WARN_LOG("failed to get mp4 size.");
2860     } else {
2861         exInfo.size += exInfo.sizeMp4;
2862     }
2863     if (exInfo.sizeExtra <= INVALID_SIZE) {
2864         MEDIA_WARN_LOG("failed to get extra size.");
2865     } else {
2866         exInfo.size += exInfo.sizeExtra;
2867     }
2868     MEDIA_DEBUG_LOG("MovingPhoto size is %{public}" PRId64, exInfo.size);
2869 }
2870 
GetEditPhotoExternalInfo(ExternalInfo & exInfo,vector<string> & attachment)2871 static void GetEditPhotoExternalInfo(ExternalInfo &exInfo, vector<string> &attachment)
2872 {
2873     MEDIA_DEBUG_LOG("GetEditPhotoExternalInfo start.");
2874     CHECK_AND_RETURN_LOG(exInfo.editTime != 0, "editTime is zero");
2875 
2876     exInfo.editDataPath = PhotoFileUtils::GetEditDataPath(exInfo.path);
2877     exInfo.editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(exInfo.path);
2878     exInfo.editDataSourcePath = PhotoFileUtils::GetEditDataSourcePath(exInfo.path);
2879     PushMovingPhotoExternalPath(exInfo.editDataPath, "editDataPath", attachment);
2880     PushMovingPhotoExternalPath(exInfo.editDataCameraPath, "editDataCameraPath", attachment);
2881     PushMovingPhotoExternalPath(exInfo.editDataSourcePath, "editDataSourcePath", attachment);
2882     MEDIA_INFO_LOG("editDataPath is %{public}s, editDataCameraPath is %{public}s, editDataSourcePath is %{public}s",
2883         DfxUtils::GetSafePath(exInfo.editDataPath).c_str(), DfxUtils::GetSafePath(exInfo.editDataCameraPath).c_str(),
2884         DfxUtils::GetSafePath(exInfo.editDataSourcePath).c_str());
2885 }
2886 
GetCleanFileInfo(shared_ptr<FileAsset> & fileAssetPtr)2887 static CleanFileInfo GetCleanFileInfo(shared_ptr<FileAsset> &fileAssetPtr)
2888 {
2889     MEDIA_DEBUG_LOG("GetCleanFileInfo start.");
2890     CHECK_AND_RETURN_RET_LOG(fileAssetPtr != nullptr, {}, "GetCleanFileInfo fileAssetPtr is nullptr.");
2891 
2892     CleanFileInfo cleanFileInfo;
2893     ExternalInfo externalInfo;
2894     externalInfo.size = fileAssetPtr->GetSize();
2895     if (externalInfo.size == INVALID_SIZE) {
2896         externalInfo.size = GetAssetSize(externalInfo.path);
2897         CHECK_AND_RETURN_RET_LOG(externalInfo.size > INVALID_SIZE, {}, "failed to get asset size.");
2898     }
2899     externalInfo.path = fileAssetPtr->GetPath();
2900     MEDIA_INFO_LOG("path is %{public}s", DfxUtils::GetSafePath(externalInfo.path).c_str());
2901     externalInfo.cloudId = fileAssetPtr->GetCloudId();
2902     externalInfo.subType = fileAssetPtr->GetPhotoSubType();
2903     externalInfo.effectMode = fileAssetPtr->GetMovingPhotoEffectMode();
2904     externalInfo.originalSubType = fileAssetPtr->GetOriginalSubType();
2905     GetMovingPhotoExternalInfo(externalInfo, cleanFileInfo.attachment);
2906     MEDIA_DEBUG_LOG("size is %{public}" PRId64, externalInfo.size);
2907     externalInfo.dateModified = fileAssetPtr->GetDateModified();
2908     externalInfo.displayName = fileAssetPtr->GetDisplayName();
2909     externalInfo.editTime = fileAssetPtr->GetPhotoEditTime();
2910     GetEditPhotoExternalInfo(externalInfo, cleanFileInfo.attachment);
2911     cleanFileInfo.cloudId = externalInfo.cloudId;
2912     cleanFileInfo.size = externalInfo.size;
2913     cleanFileInfo.modifiedTime = externalInfo.dateModified;
2914     cleanFileInfo.path = externalInfo.path;
2915     cleanFileInfo.fileName = externalInfo.displayName;
2916     return cleanFileInfo;
2917 }
2918 
GetBurstFileInfo(const string & key,vector<CleanFileInfo> & fileInfos)2919 static int32_t GetBurstFileInfo(const string &key, vector<CleanFileInfo> &fileInfos)
2920 {
2921     MEDIA_DEBUG_LOG("GetBurstFileInfo start.");
2922     AbsRdbPredicates rbdPredicates(PhotoColumn::PHOTOS_TABLE);
2923     rbdPredicates.EqualTo(PhotoColumn::PHOTO_BURST_KEY, key);
2924     vector<string> columns = {
2925         PhotoColumn::PHOTO_CLOUD_ID,
2926         MediaColumn::MEDIA_SIZE,
2927         MediaColumn::MEDIA_DATE_MODIFIED,
2928         MediaColumn::MEDIA_FILE_PATH,
2929         MediaColumn::MEDIA_NAME,
2930         MediaColumn::MEDIA_ID,
2931         PhotoColumn::PHOTO_POSITION,
2932         PhotoColumn::PHOTO_BURST_KEY,
2933         PhotoColumn::PHOTO_SUBTYPE,
2934         PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
2935         PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
2936         PhotoColumn::PHOTO_EDIT_TIME,
2937     };
2938 
2939     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rbdPredicates, columns);
2940     vector<shared_ptr<FileAsset>> fileAssetVector;
2941     GetFileAssetsFromResultSet(resultSet, columns, fileAssetVector);
2942     CHECK_AND_RETURN_RET_LOG(!fileAssetVector.empty(), E_HAS_DB_ERROR,
2943         "GetBurstFileInfo fileAssetVector is empty.");
2944     for (auto& fileAssetPtr : fileAssetVector) {
2945         fileInfos.push_back(GetCleanFileInfo(fileAssetPtr));
2946     }
2947     return E_OK;
2948 }
2949 
BatchDeleteLocalAndCloud(const vector<CleanFileInfo> & fileInfos)2950 static void BatchDeleteLocalAndCloud(const vector<CleanFileInfo> &fileInfos)
2951 {
2952     CHECK_AND_RETURN_LOG(!fileInfos.empty(), "Batch delete local and cloud fileInfo is empty.");
2953     vector<string> failCloudId;
2954     MediaLibraryTracer tracer;
2955     tracer.Start("BatchDeleteLocalAndCloud");
2956     auto ret = CloudSyncManager::GetInstance().BatchCleanFile(fileInfos, failCloudId);
2957     if (ret != 0) {
2958         MEDIA_ERR_LOG("Failed to delete local and cloud photos permanently.");
2959     } else if (!failCloudId.empty()) {
2960         for (const auto& element : failCloudId) {
2961             MEDIA_ERR_LOG("Failed to delete, cloudId is %{public}s.", element.c_str());
2962         }
2963     } else {
2964         MEDIA_DEBUG_LOG("Delete local and cloud photos permanently success");
2965     }
2966 }
2967 
DeleteLocalAndCloudPhotos(vector<shared_ptr<FileAsset>> & subFileAsset)2968 static int32_t DeleteLocalAndCloudPhotos(vector<shared_ptr<FileAsset>> &subFileAsset)
2969 {
2970     MediaLibraryTracer tracer;
2971     tracer.Start("DeleteLocalAndCloudPhotos");
2972     MEDIA_DEBUG_LOG("DeleteLocalAndCloudPhotos start.");
2973     vector<CleanFileInfo> fileInfos;
2974     if (subFileAsset.empty()) {
2975         MEDIA_INFO_LOG("DeleteLocalAndCloudPhotos subFileAsset is empty.");
2976         return E_OK;
2977     }
2978 
2979     for (auto& fileAssetPtr : subFileAsset) {
2980         if (fileAssetPtr == nullptr) {
2981             continue;
2982         }
2983         string burst_key = fileAssetPtr->GetBurstKey();
2984         if (burst_key != "") {
2985             GetBurstFileInfo(burst_key, fileInfos);
2986             continue;
2987         }
2988         fileInfos.push_back(GetCleanFileInfo(fileAssetPtr));
2989     }
2990     vector<CleanFileInfo> subFileInfo;
2991     int32_t count = 0;
2992     for (const auto& element : fileInfos) {
2993         MEDIA_INFO_LOG("delete local and cloud file displayName is %{public}s", element.fileName.c_str());
2994         subFileInfo.push_back(element);
2995         count++;
2996         if (count == MAX_PROCESS_NUM) {
2997             BatchDeleteLocalAndCloud(subFileInfo);
2998             subFileInfo.clear();
2999             count = 0;
3000         }
3001     }
3002     if (!subFileInfo.empty()) {
3003         BatchDeleteLocalAndCloud(subFileInfo);
3004     }
3005     return E_OK;
3006 }
3007 
DeleteDbByIds(const string & table,vector<string> & ids,const bool compatible)3008 static inline int32_t DeleteDbByIds(const string &table, vector<string> &ids, const bool compatible)
3009 {
3010     AbsRdbPredicates predicates(table);
3011     predicates.In(MediaColumn::MEDIA_ID, ids);
3012     if (!compatible) {
3013         predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
3014     }
3015     return MediaLibraryRdbStore::Delete(predicates);
3016 }
3017 
3018 /**
3019  * @brief Delete files permanently from system.
3020  *
3021  * @param predicates Files to delete.
3022  * @param isAging Whether in aging process.
3023  * @param compatible API8 interfaces can delete files directly without trash.
3024  *   true: Delete files, may including non-trashed files.
3025  *   false: Only delete files that were already trashed.
3026  * @return Return deleted rows
3027  */
DeleteFromDisk(AbsRdbPredicates & predicates,const bool isAging,const bool compatible)3028 int32_t MediaLibraryAssetOperations::DeleteFromDisk(AbsRdbPredicates &predicates,
3029     const bool isAging, const bool compatible)
3030 {
3031     MediaLibraryTracer tracer;
3032     tracer.Start("DeleteFromDisk");
3033     MEDIA_INFO_LOG("DeleteFromDisk start");
3034     vector<string> whereArgs = predicates.GetWhereArgs();
3035     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
3036     vector<string> agingNotifyUris;
3037 
3038     // Query asset uris for notify before delete.
3039     if (isAging) {
3040         MediaLibraryNotify::GetNotifyUris(predicates, agingNotifyUris);
3041     }
3042     DeletedFilesParams fileParams;
3043     int32_t deletedRows = 0;
3044     GetIdsAndPaths(predicates, fileParams);
3045     CHECK_AND_RETURN_RET_LOG(!fileParams.ids.empty(), deletedRows, "Failed to delete files in db, ids size: 0");
3046 
3047     // notify deferred processing session to remove image
3048     MultiStagesCaptureManager::RemovePhotos(predicates, false);
3049 
3050     // delete cloud enhanacement task
3051 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
3052     vector<string> photoIds;
3053     EnhancementManager::GetInstance().RemoveTasksInternal(fileParams.ids, photoIds);
3054 #endif
3055 
3056     deletedRows = DeleteDbByIds(predicates.GetTableName(), fileParams.ids, compatible);
3057     CHECK_AND_RETURN_RET_LOG(deletedRows > 0, deletedRows,
3058         "Failed to delete files in db, deletedRows: %{public}d, ids size: %{public}zu",
3059         deletedRows, fileParams.ids.size());
3060 
3061     MEDIA_INFO_LOG("Delete files in db, deletedRows: %{public}d", deletedRows);
3062     auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
3063     CHECK_AND_RETURN_RET_LOG(asyncWorker != nullptr, E_ERR, "Can not get asyncWorker");
3064 
3065     const vector<string> &notifyUris = isAging ? agingNotifyUris : whereArgs;
3066     string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
3067     auto *taskData = new (nothrow) DeleteFilesTask(fileParams.ids, fileParams.paths, notifyUris,
3068         fileParams.dateTakens, fileParams.subTypes,
3069         predicates.GetTableName(), deletedRows, bundleName);
3070     taskData->isTemps_.swap(fileParams.isTemps);
3071     CHECK_AND_RETURN_RET_LOG(taskData != nullptr, E_ERR, "Failed to alloc async data for Delete From Disk!");
3072     auto deleteFilesTask = make_shared<MediaLibraryAsyncTask>(DeleteFiles, taskData);
3073     CHECK_AND_RETURN_RET_LOG(deleteFilesTask != nullptr, E_ERR, "Failed to create async task for deleting files.");
3074     asyncWorker->AddTask(deleteFilesTask, true);
3075 
3076     CloudMediaAssetManager::GetInstance().SetIsThumbnailUpdate();
3077     return deletedRows;
3078 }
3079 
GetAlbumTypeSubTypeById(const string & albumId,PhotoAlbumType & type,PhotoAlbumSubType & subType)3080 static int32_t GetAlbumTypeSubTypeById(const string &albumId, PhotoAlbumType &type, PhotoAlbumSubType &subType)
3081 {
3082     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
3083     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, albumId);
3084     vector<string> columns = { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE };
3085     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
3086     if (resultSet == nullptr) {
3087         MEDIA_ERR_LOG("album id %{private}s is not exist", albumId.c_str());
3088         return E_INVALID_ARGUMENTS;
3089     }
3090     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_INVALID_ARGUMENTS,
3091         "album id is not exist");
3092     type = static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet));
3093     subType = static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet));
3094     resultSet->Close();
3095     return E_SUCCESS;
3096 }
3097 
NotifyPhotoAlbum(const vector<int32_t> & changedAlbumIds)3098 static void NotifyPhotoAlbum(const vector<int32_t> &changedAlbumIds)
3099 {
3100     if (changedAlbumIds.size() <= 0) {
3101         return;
3102     }
3103     for (int32_t albumId : changedAlbumIds) {
3104         MEDIA_DEBUG_LOG("NotifyPortraitAlbum album id is %{public}d", albumId);
3105         PhotoAlbumType type;
3106         PhotoAlbumSubType subType;
3107         int32_t ret = GetAlbumTypeSubTypeById(to_string(albumId), type, subType);
3108         if (ret != E_SUCCESS) {
3109             MEDIA_ERR_LOG("Get album type and subType by album id failed");
3110             continue;
3111         }
3112         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3113         if (rdbStore == nullptr) {
3114             MEDIA_ERR_LOG("Failed to get rdbStore.");
3115             continue;
3116         }
3117         if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
3118             MediaLibraryRdbUtils::UpdateUserAlbumInternal(
3119                 rdbStore, { to_string(albumId) }, true);
3120         } else if (PhotoAlbum::IsSourceAlbum(type, subType)) {
3121             MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
3122                 rdbStore, { to_string(albumId) }, true);
3123         } else {
3124             MEDIA_WARN_LOG("Can't find album id %{public}d in User and Source Album", albumId);
3125         }
3126     }
3127     MediaLibraryRdbUtils::UpdateSystemAlbumExcludeSource(true);
3128 }
3129 
DeleteNormalPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3130 int32_t MediaLibraryAssetOperations::DeleteNormalPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3131 {
3132     MediaLibraryTracer tracer;
3133     tracer.Start("DeleteNormalPhotoPermanently");
3134     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3135         "Photo Asset is nullptr");
3136     string filePath = fileAsset->GetPath();
3137     string displayName = fileAsset->GetDisplayName();
3138     MEDIA_INFO_LOG("Delete Photo displayName is %{public}s", displayName.c_str());
3139     MEDIA_DEBUG_LOG("Delete Photo path is %{public}s", filePath.c_str());
3140     CHECK_AND_RETURN_RET_LOG(!filePath.empty(), E_INVALID_PATH, "get file path failed");
3141     bool res = MediaFileUtils::DeleteFile(filePath);
3142     CHECK_AND_RETURN_RET_LOG(res, E_HAS_FS_ERROR, "Delete photo file failed, errno: %{public}d", errno);
3143 
3144     //delete thumbnail
3145     int32_t fileId = fileAsset->GetId();
3146     MediaLibraryAssetOperations::InvalidateThumbnail(to_string(fileId), fileAsset->GetMediaType());
3147 
3148     // delete file in db
3149     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::DELETE);
3150     cmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::MEDIA_ID, to_string(fileId));
3151     int32_t deleteRows = DeleteAssetInDb(cmd);
3152     MEDIA_DEBUG_LOG("Total delete row in db is %{public}d", deleteRows);
3153     CHECK_AND_RETURN_RET_LOG(deleteRows > 0, E_HAS_DB_ERROR,
3154         "Delete photo in database failed, errCode=%{public}d", deleteRows);
3155 
3156     auto watch = MediaLibraryNotify::GetInstance();
3157     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_HAS_FS_ERROR, "watch is nullptr");
3158     string notifyDeleteUri =
3159         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(deleteRows),
3160             MediaFileUtils::GetExtraUri(displayName, filePath));
3161     watch->Notify(notifyDeleteUri, NotifyType::NOTIFY_REMOVE);
3162     std::vector<std::string> notifyDeleteUris;
3163     notifyDeleteUris.push_back(notifyDeleteUri);
3164     auto dfxManager = DfxManager::GetInstance();
3165     if (dfxManager != nullptr) {
3166         dfxManager->HandleDeleteBehavior(DfxType::DELETE_LOCAL_ASSETS_PERMANENTLY, deleteRows, notifyDeleteUris);
3167     }
3168     MediaLibraryPhotoOperations::DeleteRevertMessage(filePath);
3169     return E_OK;
3170 }
3171 
DeletePhotoPermanentlyFromVector(vector<shared_ptr<FileAsset>> & fileAssetVector)3172 static int32_t DeletePhotoPermanentlyFromVector(vector<shared_ptr<FileAsset>> &fileAssetVector)
3173 {
3174     for (auto& fileAssetPtr : fileAssetVector) {
3175         MEDIA_DEBUG_LOG("Delete photo display name %{public}s", fileAssetPtr->GetDisplayName().c_str());
3176         CHECK_AND_RETURN_RET_LOG(fileAssetPtr != nullptr, E_HAS_DB_ERROR,
3177             "Photo Asset is nullptr");
3178         MediaLibraryAssetOperations::DeleteNormalPhotoPermanently(fileAssetPtr);
3179     }
3180     return E_OK;
3181 }
3182 
DeleteBurstPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3183 static int32_t DeleteBurstPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3184 {
3185     MEDIA_DEBUG_LOG("DeleteBurstPhotoPermanently begin");
3186     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3187         "Photo Asset is nullptr");
3188     string burstKey = fileAsset->GetBurstKey();
3189     MEDIA_DEBUG_LOG("Deleteburst is %{public}s", burstKey.c_str());
3190     CHECK_AND_RETURN_RET(burstKey != "", E_OK);
3191 
3192     vector<shared_ptr<FileAsset>> burstFileAssetVector;
3193     AbsRdbPredicates rbdPredicates(PhotoColumn::PHOTOS_TABLE);
3194     rbdPredicates.EqualTo(PhotoColumn::PHOTO_BURST_KEY, burstKey);
3195     vector<string> columns = {
3196         MediaColumn::MEDIA_FILE_PATH,
3197         MediaColumn::MEDIA_ID,
3198         MediaColumn::MEDIA_TYPE,
3199     };
3200     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rbdPredicates, columns);
3201     GetFileAssetsFromResultSet(resultSet, columns, burstFileAssetVector);
3202     DeletePhotoPermanentlyFromVector(burstFileAssetVector);
3203     return E_OK;
3204 }
3205 
DeleteMovingPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3206 static int32_t DeleteMovingPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3207 {
3208     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Photo Asset is nullptr");
3209     int32_t subType = fileAsset->GetPhotoSubType();
3210     int32_t effectMode = fileAsset->GetMovingPhotoEffectMode();
3211     int32_t originalSubType = fileAsset->GetOriginalSubType();
3212     if (MovingPhotoFileUtils::IsMovingPhoto(subType, effectMode, originalSubType)) {
3213         string path = fileAsset->GetPath();
3214         string videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(path);
3215         if (!MediaFileUtils::DeleteFile(videoPath)) {
3216             MEDIA_INFO_LOG("delete video path is %{public}s, errno: %{public}d",
3217                 DfxUtils::GetSafePath(videoPath).c_str(), errno);
3218         }
3219         string exVideoPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(path);
3220         if (!MediaFileUtils::DeleteFile(exVideoPath)) {
3221             MEDIA_INFO_LOG("delete extra video path is %{public}s, errno: %{public}d",
3222                 DfxUtils::GetSafePath(exVideoPath).c_str(), errno);
3223         }
3224         string sourceImagePath = MovingPhotoFileUtils::GetSourceMovingPhotoImagePath(path);
3225         if (!MediaFileUtils::DeleteFile(sourceImagePath)) {
3226             MEDIA_INFO_LOG("delete source image path is %{public}s, errno: %{public}d",
3227                 DfxUtils::GetSafePath(sourceImagePath).c_str(), errno);
3228         }
3229         string sourceVideoPath = MovingPhotoFileUtils::GetSourceMovingPhotoVideoPath(path);
3230         if (!MediaFileUtils::DeleteFile(sourceVideoPath)) {
3231             MEDIA_INFO_LOG("delete source video path is %{public}s, errno: %{public}d",
3232                 DfxUtils::GetSafePath(sourceVideoPath).c_str(), errno);
3233         }
3234         string livePhotoCachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(path);
3235         if (!MediaFileUtils::DeleteFile(livePhotoCachePath)) {
3236             MEDIA_INFO_LOG("delete live photo cache path is %{public}s, errno: %{public}d",
3237                 DfxUtils::GetSafePath(livePhotoCachePath).c_str(), errno);
3238         }
3239     }
3240     return E_OK;
3241 }
3242 
DeleteEditPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3243 static int32_t DeleteEditPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3244 {
3245     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3246         "Photo Asset is nullptr");
3247     int64_t editTime = fileAsset->GetPhotoEditTime();
3248     if (editTime != 0) {
3249         string path = fileAsset->GetPath();
3250         string editDataPath = PhotoFileUtils::GetEditDataPath(path);
3251         MEDIA_DEBUG_LOG("edit photo editDataPath path is %{public}s", editDataPath.c_str());
3252         if (!MediaFileUtils::DeleteFile(editDataPath)) {
3253             MEDIA_INFO_LOG("delete edit data path is %{public}s, errno: %{public}d",
3254                 DfxUtils::GetSafePath(editDataPath).c_str(), errno);
3255         }
3256         string editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(path);
3257         if (!MediaFileUtils::DeleteFile(editDataCameraPath)) {
3258             MEDIA_INFO_LOG("delete edit data camera path is %{public}s, errno: %{public}d",
3259                 DfxUtils::GetSafePath(editDataCameraPath).c_str(), errno);
3260         }
3261     }
3262     return E_OK;
3263 }
3264 
DeleteLocalPhotoPermanently(shared_ptr<FileAsset> & fileAsset,vector<shared_ptr<FileAsset>> & subFileAssetVector)3265 static int32_t DeleteLocalPhotoPermanently(shared_ptr<FileAsset> &fileAsset,
3266     vector<shared_ptr<FileAsset>> &subFileAssetVector)
3267 {
3268     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3269         "Photo Asset is nullptr");
3270     int32_t position = fileAsset->GetPosition();
3271     MEDIA_DEBUG_LOG("Photo position is %{public}d", position);
3272     if (position == LOCAL_PHOTO_POSITION) {
3273         int32_t id = fileAsset->GetId();
3274         CHECK_AND_PRINT_LOG(DeleteEditPhotoPermanently(fileAsset) == E_OK,
3275             "Delete edit photo file failed id %{public}d", id);
3276 
3277         CHECK_AND_PRINT_LOG(DeleteMovingPhotoPermanently(fileAsset) == E_OK,
3278             "Delete moving photo file failed id %{public}d", id);
3279 
3280         CHECK_AND_PRINT_LOG(DeleteBurstPhotoPermanently(fileAsset) == E_OK,
3281             "Delete moving photo file failed id %{public}d", id);
3282 
3283         CHECK_AND_PRINT_LOG(MediaLibraryAssetOperations::DeleteNormalPhotoPermanently(fileAsset) == E_OK,
3284             "Delete moving photo file failed id %{public}d", id);
3285     }
3286     if (position == CLOUD_PHOTO_POSITION) {
3287         MEDIA_DEBUG_LOG("Don't delete cloud Photo");
3288     }
3289     if (position == BOTH_LOCAL_CLOUD_PHOTO_POSITION) {
3290         subFileAssetVector.push_back(fileAsset);
3291     }
3292     return E_OK;
3293 }
3294 
DeletePermanently(AbsRdbPredicates & predicates,const bool isAging)3295 int32_t MediaLibraryAssetOperations::DeletePermanently(AbsRdbPredicates &predicates, const bool isAging)
3296 {
3297     MEDIA_DEBUG_LOG("DeletePermanently begin");
3298     MediaLibraryTracer tracer;
3299     tracer.Start("DeletePermanently");
3300     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
3301     vector<string> agingNotifyUris;
3302 
3303     // Query asset uris for notify before delete.
3304     if (isAging) {
3305         MediaLibraryNotify::GetNotifyUris(predicates, agingNotifyUris);
3306     }
3307 
3308     vector<string> columns = {
3309         PhotoColumn::PHOTO_CLOUD_ID,
3310         MediaColumn::MEDIA_SIZE,
3311         MediaColumn::MEDIA_DATE_MODIFIED,
3312         MediaColumn::MEDIA_FILE_PATH,
3313         MediaColumn::MEDIA_NAME,
3314         MediaColumn::MEDIA_ID,
3315         PhotoColumn::PHOTO_POSITION,
3316         PhotoColumn::PHOTO_BURST_KEY,
3317         MediaColumn::MEDIA_TYPE,
3318         PhotoColumn::PHOTO_SUBTYPE,
3319         PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
3320         PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
3321         PhotoColumn::PHOTO_EDIT_TIME,
3322         PhotoColumn::PHOTO_OWNER_ALBUM_ID,
3323     };
3324     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
3325     vector<shared_ptr<FileAsset>> fileAssetVector;
3326     vector<shared_ptr<FileAsset>> subFileAssetVector;
3327     std::set<int32_t> changedAlbumIds;
3328     GetAssetVectorFromResultSet(resultSet, columns, fileAssetVector);
3329     for (auto& fileAssetPtr : fileAssetVector) {
3330         DeleteLocalPhotoPermanently(fileAssetPtr, subFileAssetVector);
3331         changedAlbumIds.insert(fileAssetPtr->GetOwnerAlbumId());
3332     }
3333 
3334     //delete both local and cloud image
3335     DeleteLocalAndCloudPhotos(subFileAssetVector);
3336     NotifyPhotoAlbum(std::vector<int32_t>(changedAlbumIds.begin(), changedAlbumIds.end()));
3337     return E_OK;
3338 }
3339 } // namespace Media
3340 } // namespace OHOS