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