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_photo_operations.h"
17 
18 #include <memory>
19 #include <mutex>
20 #include <nlohmann/json.hpp>
21 #include <thread>
22 
23 #include "abs_shared_result_set.h"
24 #include "directory_ex.h"
25 #include "duplicate_photo_operation.h"
26 #include "file_asset.h"
27 #include "file_utils.h"
28 #include "media_analysis_helper.h"
29 #include "image_packer.h"
30 #include "iservice_registry.h"
31 #include "media_change_effect.h"
32 #include "media_column.h"
33 #include "media_file_uri.h"
34 #include "media_file_utils.h"
35 #include "media_log.h"
36 #include "medialibrary_album_fusion_utils.h"
37 #include "medialibrary_album_operations.h"
38 #include "medialibrary_analysis_album_operations.h"
39 #include "medialibrary_asset_operations.h"
40 #include "medialibrary_command.h"
41 #include "medialibrary_data_manager_utils.h"
42 #include "medialibrary_db_const.h"
43 #include "medialibrary_errno.h"
44 #include "medialibrary_inotify.h"
45 #include "medialibrary_notify.h"
46 #include "medialibrary_object_utils.h"
47 #include "medialibrary_rdb_utils.h"
48 #include "medialibrary_rdb_transaction.h"
49 #include "medialibrary_rdbstore.h"
50 #include "medialibrary_tracer.h"
51 #include "medialibrary_type_const.h"
52 #include "medialibrary_uripermission_operations.h"
53 #include "medialibrary_vision_operations.h"
54 #include "mimetype_utils.h"
55 #include "multistages_capture_manager.h"
56 #include "enhancement_manager.h"
57 #include "parameters.h"
58 #include "permission_utils.h"
59 #include "photo_album_column.h"
60 #include "photo_map_column.h"
61 #include "photo_map_operations.h"
62 #include "picture.h"
63 #include "image_type.h"
64 #include "picture_manager_thread.h"
65 
66 #include "rdb_predicates.h"
67 #include "result_set_utils.h"
68 #include "thumbnail_const.h"
69 #include "uri.h"
70 #include "userfile_manager_types.h"
71 #include "value_object.h"
72 #include "values_bucket.h"
73 #include "vision_column.h"
74 #include "medialibrary_formmap_operations.h"
75 #include "dfx_const.h"
76 #include "dfx_manager.h"
77 #include "hi_audit.h"
78 #include "moving_photo_file_utils.h"
79 
80 using namespace OHOS::DataShare;
81 using namespace std;
82 using namespace OHOS::NativeRdb;
83 using namespace OHOS::RdbDataShareAdapter;
84 
85 namespace OHOS {
86 namespace Media {
87 static const string ANALYSIS_HAS_DATA = "1";
88 constexpr int SAVE_PHOTO_WAIT_MS = 300;
89 constexpr int TASK_NUMBER_MAX = 5;
90 enum ImageFileType : int32_t {
91     JPEG = 1,
92     HEIF = 2
93 };
94 
95 const std::string MIME_TYPE_JPEG = "image/jpeg";
96 
97 const std::string MIME_TYPE_HEIF = "image/heic";
98 
99 const std::string EXTENSION_JPEG = ".jpg";
100 
101 const std::string EXTENSION_HEIF = ".heic";
102 
103 const std::unordered_map<ImageFileType, std::string> IMAGE_FILE_TYPE_MAP = {
104     {JPEG, MIME_TYPE_JPEG},
105     {HEIF, MIME_TYPE_HEIF},
106 };
107 
108 const std::unordered_map<ImageFileType, std::string> IMAGE_EXTENSION_MAP = {
109     {JPEG, EXTENSION_JPEG},
110     {HEIF, EXTENSION_HEIF},
111 };
112 const string PHOTO_ALBUM_URI_PREFIX_V0 = "file://media/PhotoAlbum/";
113 shared_ptr<PhotoEditingRecord> PhotoEditingRecord::instance_ = nullptr;
114 mutex PhotoEditingRecord::mutex_;
115 std::mutex MediaLibraryPhotoOperations::saveCameraPhotoMutex_;
116 std::condition_variable MediaLibraryPhotoOperations::condition_;
117 std::string MediaLibraryPhotoOperations::lastPhotoId_ = "default";
Create(MediaLibraryCommand & cmd)118 int32_t MediaLibraryPhotoOperations::Create(MediaLibraryCommand &cmd)
119 {
120     switch (cmd.GetApi()) {
121         case MediaLibraryApi::API_10:
122             return CreateV10(cmd);
123         case MediaLibraryApi::API_OLD:
124             return CreateV9(cmd);
125         default:
126             MEDIA_ERR_LOG("get api failed");
127             return E_FAIL;
128     }
129 }
130 
DeleteCache(MediaLibraryCommand & cmd)131 int32_t MediaLibraryPhotoOperations::DeleteCache(MediaLibraryCommand& cmd)
132 {
133     string uriString = cmd.GetUriStringWithoutSegment();
134     if (!MediaFileUtils::StartsWith(uriString, PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
135         return E_INVALID_VALUES;
136     }
137 
138     string fileName = uriString.substr(PhotoColumn::PHOTO_CACHE_URI_PREFIX.size());
139     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckDisplayName(fileName) == E_OK, E_INVALID_URI,
140         "Check fileName failed, fileName=%{private}s", fileName.c_str());
141     string cacheDir = GetAssetCacheDir();
142     string path = cacheDir + "/" + fileName;
143     if (!MediaFileUtils::DeleteFile(path)) {
144         MEDIA_ERR_LOG("Delete cache file failed, errno: %{public}d, uri: %{private}s", errno, uriString.c_str());
145         return E_HAS_FS_ERROR;
146     }
147     return E_OK;
148 }
149 
Delete(MediaLibraryCommand & cmd)150 int32_t MediaLibraryPhotoOperations::Delete(MediaLibraryCommand& cmd)
151 {
152     // delete file in .cache
153     if (MediaFileUtils::StartsWith(cmd.GetUri().ToString(), PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
154         return DeleteCache(cmd);
155     }
156 
157     string fileId = cmd.GetOprnFileId();
158     vector<string> columns = {
159         PhotoColumn::MEDIA_ID,
160         PhotoColumn::MEDIA_FILE_PATH,
161         PhotoColumn::MEDIA_RELATIVE_PATH,
162         PhotoColumn::MEDIA_TYPE
163     };
164     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
165         cmd.GetOprnObject(), columns);
166     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_FILEID, "Get fileAsset failed, fileId: %{private}s",
167         fileId.c_str());
168     int32_t deleteRow = DeletePhoto(fileAsset, cmd.GetApi());
169     CHECK_AND_RETURN_RET_LOG(deleteRow >= 0, deleteRow, "delete photo failed, deleteRow=%{public}d", deleteRow);
170 
171     return deleteRow;
172 }
173 
GetAlbumTypeSubTypeById(const string & albumId,PhotoAlbumType & type,PhotoAlbumSubType & subType)174 static int32_t GetAlbumTypeSubTypeById(const string &albumId, PhotoAlbumType &type, PhotoAlbumSubType &subType)
175 {
176     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
177     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, albumId);
178     vector<string> columns = { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE };
179     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
180     if (resultSet == nullptr) {
181         MEDIA_ERR_LOG("album id %{private}s is not exist", albumId.c_str());
182         return E_INVALID_ARGUMENTS;
183     }
184     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_INVALID_ARGUMENTS,
185         "album id is not exist");
186     type = static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet));
187     subType = static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet));
188     resultSet->Close();
189     return E_SUCCESS;
190 }
191 
GetPredicatesByAlbumId(const string & albumId,RdbPredicates & predicates)192 static int32_t GetPredicatesByAlbumId(const string &albumId, RdbPredicates &predicates)
193 {
194     PhotoAlbumType type;
195     PhotoAlbumSubType subType;
196     CHECK_AND_RETURN_RET_LOG(GetAlbumTypeSubTypeById(albumId, type, subType) == E_SUCCESS, E_INVALID_ARGUMENTS,
197         "invalid album uri");
198 
199     if ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType))) {
200         MEDIA_ERR_LOG("album id %{private}s type:%d subtype:%d", albumId.c_str(), type, subType);
201         return E_INVALID_ARGUMENTS;
202     }
203 
204     if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
205         PhotoAlbumColumns::GetUserAlbumPredicates(stoi(albumId), predicates, false);
206         return E_SUCCESS;
207     }
208 
209     if (PhotoAlbum::IsSourceAlbum(type, subType)) {
210         PhotoAlbumColumns::GetSourceAlbumPredicates(stoi(albumId), predicates, false);
211         return E_SUCCESS;
212     }
213 
214     if ((type != PhotoAlbumType::SYSTEM) || (subType == PhotoAlbumSubType::USER_GENERIC) ||
215         (subType == PhotoAlbumSubType::ANY)) {
216         MEDIA_ERR_LOG("album id %{private}s type:%d subtype:%d", albumId.c_str(), type, subType);
217         return E_INVALID_ARGUMENTS;
218     }
219     PhotoAlbumColumns::GetSystemAlbumPredicates(subType, predicates, false);
220     return E_SUCCESS;
221 }
222 
GetValidOrderClause(const DataSharePredicates & predicate,string & clause)223 static bool GetValidOrderClause(const DataSharePredicates &predicate, string &clause)
224 {
225     constexpr int32_t FIELD_IDX = 0;
226     vector<OperationItem> operations;
227     const auto &items = predicate.GetOperationList();
228     int32_t count = 0;
229     clause = "ROW_NUMBER() OVER (ORDER BY ";
230     for (const auto &item : items) {
231         if (item.operation == ORDER_BY_ASC) {
232             count++;
233             clause += static_cast<string>(item.GetSingle(FIELD_IDX)) + " ASC) as " + PHOTO_INDEX;
234         } else if (item.operation == ORDER_BY_DESC) {
235             count++;
236             clause += static_cast<string>(item.GetSingle(FIELD_IDX)) + " DESC) as " + PHOTO_INDEX;
237         }
238     }
239 
240     // only support orderby with one item
241     return (count == 1);
242 }
243 
AppendValidOrderClause(MediaLibraryCommand & cmd,RdbPredicates & predicates,const string & photoId)244 static bool AppendValidOrderClause(MediaLibraryCommand &cmd, RdbPredicates &predicates, const string &photoId)
245 {
246     constexpr int32_t FIELD_IDX = 0;
247     const auto &items = cmd.GetDataSharePred().GetOperationList();
248     int32_t count = 0;
249     string dateType;
250     string comparisonOperator;
251     for (const auto &item : items) {
252         if (item.operation == ORDER_BY_ASC) {
253             count++;
254             dateType = static_cast<string>(item.GetSingle(FIELD_IDX)) == MediaColumn::MEDIA_DATE_TAKEN ?
255                 MediaColumn::MEDIA_DATE_TAKEN : MediaColumn::MEDIA_DATE_ADDED;
256             comparisonOperator = " <= ";
257         } else if (item.operation == ORDER_BY_DESC) {
258             count++;
259             dateType = static_cast<string>(item.GetSingle(FIELD_IDX)) == MediaColumn::MEDIA_DATE_TAKEN ?
260                 MediaColumn::MEDIA_DATE_TAKEN : MediaColumn::MEDIA_DATE_ADDED;
261             comparisonOperator = " >= ";
262         }
263     }
264     string columnName = " (" + dateType + ", " + MediaColumn::MEDIA_ID + ") ";
265     string value = " (SELECT " + dateType + ", " + MediaColumn::MEDIA_ID + " FROM " +
266         PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_ID + " = " + photoId + ") ";
267     string whereClause = predicates.GetWhereClause();
268     whereClause += " AND " + columnName + comparisonOperator + value;
269     predicates.SetWhereClause(whereClause);
270 
271     // only support orderby with one item
272     return (count == 1);
273 }
274 
HandleAlbumIndexOfUri(MediaLibraryCommand & cmd,const string & photoId,const string & albumId)275 static shared_ptr<NativeRdb::ResultSet> HandleAlbumIndexOfUri(MediaLibraryCommand &cmd, const string &photoId,
276     const string &albumId)
277 {
278     string orderClause;
279     CHECK_AND_RETURN_RET_LOG(GetValidOrderClause(cmd.GetDataSharePred(), orderClause), nullptr, "invalid orderby");
280     vector<string> columns;
281     columns.push_back(orderClause);
282     columns.push_back(MediaColumn::MEDIA_ID);
283     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
284     CHECK_AND_RETURN_RET_LOG(GetPredicatesByAlbumId(albumId, predicates) == E_SUCCESS, nullptr, "invalid album uri");
285     return MediaLibraryRdbStore::GetIndexOfUri(predicates, columns, photoId);
286 }
287 
HandleIndexOfUri(MediaLibraryCommand & cmd,RdbPredicates & predicates,const string & photoId,const string & albumId)288 static shared_ptr<NativeRdb::ResultSet> HandleIndexOfUri(MediaLibraryCommand &cmd, RdbPredicates &predicates,
289     const string &photoId, const string &albumId)
290 {
291     if (!albumId.empty()) {
292         return HandleAlbumIndexOfUri(cmd, photoId, albumId);
293     }
294     string indexClause = " COUNT(*) as " + PHOTO_INDEX;
295     vector<string> columns;
296     columns.push_back(indexClause);
297     predicates.And()->EqualTo(
298         PhotoColumn::PHOTO_SYNC_STATUS, std::to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)));
299     predicates.And()->EqualTo(
300         PhotoColumn::PHOTO_CLEAN_FLAG, std::to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)));
301     CHECK_AND_RETURN_RET_LOG(AppendValidOrderClause(cmd, predicates, photoId), nullptr, "invalid orderby");
302     return MediaLibraryRdbStore::GetIndexOfUriForPhotos(predicates, columns, photoId);
303 }
304 
HandleAnalysisIndex(MediaLibraryCommand & cmd,const string & photoId,const string & albumId)305 static shared_ptr<NativeRdb::ResultSet> HandleAnalysisIndex(MediaLibraryCommand &cmd,
306     const string &photoId, const string &albumId)
307 {
308     string orderClause;
309     CHECK_AND_RETURN_RET_LOG(GetValidOrderClause(cmd.GetDataSharePred(), orderClause), nullptr, "invalid orderby");
310     CHECK_AND_RETURN_RET_LOG(albumId.size() > 0, nullptr, "null albumId");
311     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
312     PhotoAlbumColumns::GetAnalysisAlbumPredicates(stoi(albumId), predicates, false);
313     vector<string> columns;
314     columns.push_back(orderClause);
315     columns.push_back(MediaColumn::MEDIA_ID);
316     return MediaLibraryRdbStore::GetIndexOfUri(predicates, columns, photoId);
317 }
318 
Query(MediaLibraryCommand & cmd,const vector<string> & columns)319 shared_ptr<NativeRdb::ResultSet> MediaLibraryPhotoOperations::Query(
320     MediaLibraryCommand &cmd, const vector<string> &columns)
321 {
322     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
323     if (cmd.GetOprnType() == OperationType::INDEX || cmd.GetOprnType() == OperationType::ANALYSIS_INDEX) {
324         constexpr int32_t COLUMN_SIZE = 2;
325         CHECK_AND_RETURN_RET_LOG(columns.size() >= COLUMN_SIZE, nullptr, "invalid id param");
326         constexpr int32_t PHOTO_ID_INDEX = 0;
327         constexpr int32_t ALBUM_ID_INDEX = 1;
328         string photoId = columns[PHOTO_ID_INDEX];
329         string albumId;
330         if (!columns[ALBUM_ID_INDEX].empty()) {
331             albumId = columns[ALBUM_ID_INDEX];
332         }
333         if (cmd.GetOprnType() == OperationType::ANALYSIS_INDEX) {
334             return HandleAnalysisIndex(cmd, photoId, albumId);
335         }
336         return HandleIndexOfUri(cmd, predicates, photoId, albumId);
337     }
338     int limit = predicates.GetLimit();
339     int offset = predicates.GetOffset();
340     if (cmd.GetOprnType() == OperationType::ALL_DUPLICATE_ASSETS) {
341         return DuplicatePhotoOperation::GetAllDuplicateAssets(columns, offset, limit);
342     }
343     if (cmd.GetOprnType() == OperationType::CAN_DEL_DUPLICATE_ASSETS) {
344         return DuplicatePhotoOperation::GetCanDelDuplicateAssets(columns, offset, limit);
345     }
346     MediaLibraryRdbUtils::AddQueryIndex(predicates, columns);
347     return MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
348 }
349 
Update(MediaLibraryCommand & cmd)350 int32_t MediaLibraryPhotoOperations::Update(MediaLibraryCommand &cmd)
351 {
352     switch (cmd.GetApi()) {
353         case MediaLibraryApi::API_10:
354             return UpdateV10(cmd);
355         case MediaLibraryApi::API_OLD:
356             return UpdateV9(cmd);
357         default:
358             MEDIA_ERR_LOG("get api failed");
359             return E_FAIL;
360     }
361 
362     return E_OK;
363 }
364 
365 const static vector<string> PHOTO_COLUMN_VECTOR = {
366     PhotoColumn::MEDIA_FILE_PATH,
367     PhotoColumn::MEDIA_TYPE,
368     PhotoColumn::MEDIA_TIME_PENDING,
369     PhotoColumn::PHOTO_SUBTYPE,
370     PhotoColumn::PHOTO_COVER_POSITION,
371     PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
372     PhotoColumn::PHOTO_BURST_COVER_LEVEL,
373     MediaColumn::MEDIA_HIDDEN,
374     MediaColumn::MEDIA_DATE_TRASHED,
375 };
376 
CheckOpenMovingPhoto(int32_t photoSubType,int32_t effectMode,const string & request)377 bool CheckOpenMovingPhoto(int32_t photoSubType, int32_t effectMode, const string& request)
378 {
379     return photoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) ||
380         (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY) &&
381         request == SOURCE_REQUEST);
382 }
383 
ProcessMovingPhotoOprnKey(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & id,bool & isMovingPhotoVideo)384 static int32_t ProcessMovingPhotoOprnKey(MediaLibraryCommand& cmd, shared_ptr<FileAsset>& fileAsset, const string& id,
385     bool& isMovingPhotoVideo)
386 {
387     string movingPhotoOprnKey = cmd.GetQuerySetParam(MEDIA_MOVING_PHOTO_OPRN_KEYWORD);
388     if (movingPhotoOprnKey == OPEN_MOVING_PHOTO_VIDEO) {
389         CHECK_AND_RETURN_RET_LOG(CheckOpenMovingPhoto(fileAsset->GetPhotoSubType(),
390             fileAsset->GetMovingPhotoEffectMode(), cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD)),
391             E_INVALID_VALUES,
392             "Non-moving photo is requesting moving photo operation, file id: %{public}s, actual subtype: %{public}d",
393             id.c_str(), fileAsset->GetPhotoSubType());
394         fileAsset->SetPath(MediaFileUtils::GetMovingPhotoVideoPath(fileAsset->GetPath()));
395         isMovingPhotoVideo = true;
396     } else if (movingPhotoOprnKey == OPEN_PRIVATE_LIVE_PHOTO) {
397         CHECK_AND_RETURN_RET_LOG(fileAsset->GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO),
398             E_INVALID_VALUES,
399             "Non-moving photo is requesting moving photo operation, file id: %{public}s, actual subtype: %{public}d",
400             id.c_str(), fileAsset->GetPhotoSubType());
401         string livePhotoPath;
402         CHECK_AND_RETURN_RET_LOG(MovingPhotoFileUtils::ConvertToLivePhoto(fileAsset->GetPath(),
403             fileAsset->GetCoverPosition(), livePhotoPath) == E_OK,
404             E_INVALID_VALUES,
405             "Failed convert to live photo");
406         fileAsset->SetPath(livePhotoPath);
407     }
408     return E_OK;
409 }
410 
UpdateLastVisitTime(MediaLibraryCommand & cmd,const string & id)411 static void UpdateLastVisitTime(MediaLibraryCommand &cmd, const string &id)
412 {
413     if (cmd.GetTableName() != PhotoColumn::PHOTOS_TABLE) {
414         return;
415     }
416     std::thread([=] {
417         int32_t changedRows = MediaLibraryRdbStore::UpdateLastVisitTime(id);
418         if (changedRows <= 0) {
419             MEDIA_ERR_LOG("update lastVisitTime Failed, changedRows = %{public}d.", changedRows);
420         }
421     }).detach();
422 }
423 
CheckPermissionToOpenFileAsset(const shared_ptr<FileAsset> & fileAsset)424 static bool CheckPermissionToOpenFileAsset(const shared_ptr<FileAsset>& fileAsset)
425 {
426     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, false, "File asset is nullptr");
427 
428     if (PermissionUtils::IsRootShell()) {
429         return true;
430     }
431 
432     if (fileAsset->GetDateTrashed() > 0) {
433         if (!(PermissionUtils::IsSystemApp() || PermissionUtils::IsNativeSAApp() ||
434             (PermissionUtils::IsHdcShell() &&
435             OHOS::system::GetBoolParameter("const.security.developermode.state", true)))) {
436             MEDIA_ERR_LOG("Non-system app is not allowed to open trashed photo, %{public}d, %{public}d, %{public}d, "
437                 "%{public}d", PermissionUtils::IsSystemApp(), PermissionUtils::IsNativeSAApp(),
438                 PermissionUtils::IsHdcShell(),
439                 OHOS::system::GetBoolParameter("const.security.developermode.state", true));
440             return false;
441         }
442     }
443 
444     if (fileAsset->IsHidden() && fileAsset->GetDateTrashed() == 0) {
445         CHECK_AND_RETURN_RET_LOG(PermissionUtils::CheckCallerPermission(PERM_MANAGE_PRIVATE_PHOTOS),
446             false, "MANAGE_PRIVATE_PHOTOS permission is required to open hidden photo");
447 
448         if (!(PermissionUtils::IsSystemApp() || PermissionUtils::IsNativeSAApp() ||
449             (PermissionUtils::IsHdcShell() &&
450             OHOS::system::GetBoolParameter("const.security.developermode.state", true)))) {
451             MEDIA_ERR_LOG("Non-system app is not allowed to open hidden photo, %{public}d, %{public}d, %{public}d, "
452                 "%{public}d", PermissionUtils::IsSystemApp(), PermissionUtils::IsNativeSAApp(),
453                 PermissionUtils::IsHdcShell(),
454                 OHOS::system::GetBoolParameter("const.security.developermode.state", true));
455             return false;
456         }
457     }
458 
459     return true;
460 }
461 
Open(MediaLibraryCommand & cmd,const string & mode)462 int32_t MediaLibraryPhotoOperations::Open(MediaLibraryCommand &cmd, const string &mode)
463 {
464     MediaLibraryTracer tracer;
465     tracer.Start("MediaLibraryPhotoOperations::Open");
466 
467     bool isCacheOperation = false;
468     int32_t errCode = OpenCache(cmd, mode, isCacheOperation);
469     if (errCode != E_OK || isCacheOperation) {
470         return errCode;
471     }
472     bool isSkipEdit = true;
473     errCode = OpenEditOperation(cmd, isSkipEdit);
474     if (errCode != E_OK || !isSkipEdit) {
475         return errCode;
476     }
477     string uriString = cmd.GetUriStringWithoutSegment();
478     string id = MediaFileUtils::GetIdFromUri(uriString);
479     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
480         return E_INVALID_URI;
481     }
482     string pendingStatus = cmd.GetQuerySetParam(MediaColumn::MEDIA_TIME_PENDING);
483     shared_ptr<FileAsset> fileAsset = GetFileAssetByUri(uriString, true,  PHOTO_COLUMN_VECTOR, pendingStatus);
484     if (fileAsset == nullptr) {
485         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, uri:%{public}s", uriString.c_str());
486         return E_INVALID_URI;
487     }
488     if (!CheckPermissionToOpenFileAsset(fileAsset)) {
489         MEDIA_ERR_LOG("Open not allowed");
490         return E_PERMISSION_DENIED;
491     }
492 
493     bool isMovingPhotoVideo = false;
494     errCode = ProcessMovingPhotoOprnKey(cmd, fileAsset, id, isMovingPhotoVideo);
495     if (errCode != E_OK) {
496         return errCode;
497     }
498     UpdateLastVisitTime(cmd, id);
499     if (uriString.find(PhotoColumn::PHOTO_URI_PREFIX) != string::npos) {
500         return OpenAsset(fileAsset, mode, MediaLibraryApi::API_10, isMovingPhotoVideo);
501     }
502     return OpenAsset(fileAsset, mode, cmd.GetApi());
503 }
504 
Close(MediaLibraryCommand & cmd)505 int32_t MediaLibraryPhotoOperations::Close(MediaLibraryCommand &cmd)
506 {
507     const ValuesBucket &values = cmd.GetValueBucket();
508     string uriString;
509     if (!GetStringFromValuesBucket(values, MEDIA_DATA_DB_URI, uriString)) {
510         return E_INVALID_VALUES;
511     }
512     string pendingStatus = cmd.GetQuerySetParam(MediaColumn::MEDIA_TIME_PENDING);
513 
514     shared_ptr<FileAsset> fileAsset = GetFileAssetByUri(uriString, true, PHOTO_COLUMN_VECTOR, pendingStatus);
515     if (fileAsset == nullptr) {
516         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, uri:%{public}s", uriString.c_str());
517         return E_INVALID_URI;
518     }
519 
520     int32_t isSync = 0;
521     int32_t errCode = 0;
522     if (GetInt32FromValuesBucket(cmd.GetValueBucket(), CLOSE_CREATE_THUMB_STATUS, isSync) &&
523         isSync == CREATE_THUMB_SYNC_STATUS) {
524         errCode = CloseAsset(fileAsset, true);
525     } else {
526         errCode = CloseAsset(fileAsset, false);
527     }
528     return errCode;
529 }
530 
SetPhotoTypeByRelativePath(const string & relativePath,FileAsset & fileAsset)531 static inline void SetPhotoTypeByRelativePath(const string &relativePath, FileAsset &fileAsset)
532 {
533     int32_t subType = static_cast<int32_t>(PhotoSubType::DEFAULT);
534     if (relativePath.compare(CAMERA_PATH) == 0) {
535         subType = static_cast<int32_t>(PhotoSubType::CAMERA);
536     } else if (relativePath.compare(SCREEN_RECORD_PATH) == 0 ||
537         relativePath.compare(SCREEN_SHOT_PATH) == 0) {
538         subType = static_cast<int32_t>(PhotoSubType::SCREENSHOT);
539     }
540 
541     fileAsset.SetPhotoSubType(subType);
542 }
543 
SetPhotoSubTypeFromCmd(MediaLibraryCommand & cmd,FileAsset & fileAsset)544 static inline void SetPhotoSubTypeFromCmd(MediaLibraryCommand &cmd, FileAsset &fileAsset)
545 {
546     int32_t subType = static_cast<int32_t>(PhotoSubType::DEFAULT);
547     ValueObject value;
548     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_SUBTYPE, value)) {
549         value.GetInt(subType);
550     }
551     fileAsset.SetPhotoSubType(subType);
552 }
553 
SetCameraShotKeyFromCmd(MediaLibraryCommand & cmd,FileAsset & fileAsset)554 static inline void SetCameraShotKeyFromCmd(MediaLibraryCommand &cmd, FileAsset &fileAsset)
555 {
556     string cameraShotKey;
557     ValueObject value;
558     if (cmd.GetValueBucket().GetObject(PhotoColumn::CAMERA_SHOT_KEY, value)) {
559         value.GetString(cameraShotKey);
560     }
561     fileAsset.SetCameraShotKey(cameraShotKey);
562 }
563 
GetCallingUid(MediaLibraryCommand & cmd)564 static inline int32_t GetCallingUid(MediaLibraryCommand &cmd)
565 {
566     int32_t callingUid = 0;
567     ValueObject value;
568     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
569         value.GetInt(callingUid);
570     }
571     return callingUid;
572 }
573 
SetCallingPackageName(MediaLibraryCommand & cmd,FileAsset & fileAsset)574 static inline void SetCallingPackageName(MediaLibraryCommand &cmd, FileAsset &fileAsset)
575 {
576     int32_t callingUid = GetCallingUid(cmd);
577     if (callingUid == 0) {
578         return;
579     }
580     string bundleName;
581     PermissionUtils::GetClientBundle(callingUid, bundleName);
582     fileAsset.SetOwnerPackage(bundleName);
583     string packageName;
584     PermissionUtils::GetPackageName(callingUid, packageName);
585     fileAsset.SetPackageName(packageName);
586 }
587 
CreateV9(MediaLibraryCommand & cmd)588 int32_t MediaLibraryPhotoOperations::CreateV9(MediaLibraryCommand& cmd)
589 {
590     FileAsset fileAsset;
591     ValuesBucket &values = cmd.GetValueBucket();
592 
593     string displayName;
594     CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, PhotoColumn::MEDIA_NAME, displayName),
595         E_HAS_DB_ERROR);
596     fileAsset.SetDisplayName(displayName);
597 
598     string relativePath;
599     CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, PhotoColumn::MEDIA_RELATIVE_PATH, relativePath),
600         E_HAS_DB_ERROR);
601     fileAsset.SetRelativePath(relativePath);
602     MediaFileUtils::FormatRelativePath(relativePath);
603 
604     int32_t mediaType = 0;
605     CHECK_AND_RETURN_RET(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_TYPE, mediaType),
606         E_HAS_DB_ERROR);
607     fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
608 
609     int32_t errCode = CheckRelativePathWithType(relativePath, mediaType);
610     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to Check RelativePath and Extention, "
611         "relativePath=%{private}s, mediaType=%{public}d", relativePath.c_str(), mediaType);
612     SetPhotoTypeByRelativePath(relativePath, fileAsset);
613     errCode = CheckDisplayNameWithType(displayName, mediaType);
614     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to Check Dir and Extention, "
615         "displayName=%{private}s, mediaType=%{public}d", displayName.c_str(), mediaType);
616     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
617     int32_t outRow = -1;
618     std::function<int(void)> func = [&]()->int {
619         errCode = SetAssetPathInCreate(fileAsset, trans);
620         if (errCode != E_OK) {
621             MEDIA_ERR_LOG("Failed to Solve FileAsset Path and Name, displayName=%{private}s", displayName.c_str());
622             return errCode;
623         }
624 
625         outRow = InsertAssetInDb(trans, cmd, fileAsset);
626         if (outRow <= 0) {
627             MEDIA_ERR_LOG("insert file in db failed, error = %{public}d", outRow);
628             return E_HAS_DB_ERROR;
629         }
630         return errCode;
631     };
632     errCode = trans->RetryTrans(func);
633     if (errCode != E_OK) {
634         MEDIA_ERR_LOG("CreateV9: tans finish fail!, ret:%{public}d", errCode);
635     }
636     return outRow;
637 }
638 
PhotosAddAsset(const int & albumId,const string & assetId,const string & extrUri)639 void PhotosAddAsset(const int &albumId, const string &assetId, const string &extrUri)
640 {
641     auto watch = MediaLibraryNotify::GetInstance();
642     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, assetId, extrUri),
643         NotifyType::NOTIFY_ALBUM_ADD_ASSET, albumId);
644 }
645 
SolvePhotoAlbumInCreate(MediaLibraryCommand & cmd,FileAsset & fileAsset)646 void MediaLibraryPhotoOperations::SolvePhotoAlbumInCreate(MediaLibraryCommand &cmd, FileAsset &fileAsset)
647 {
648     ValuesBucket &values = cmd.GetValueBucket();
649     string albumUri;
650     GetStringFromValuesBucket(values, MEDIA_DATA_DB_ALBUM_ID, albumUri);
651     if (!albumUri.empty()) {
652         PhotosAddAsset(stoi(MediaFileUtils::GetIdFromUri(albumUri)), to_string(fileAsset.GetId()),
653             MediaFileUtils::GetExtraUri(fileAsset.GetDisplayName(), fileAsset.GetPath()));
654     }
655 }
656 
SetAssetDisplayName(const string & displayName,FileAsset & fileAsset,bool & isContains)657 static void SetAssetDisplayName(const string &displayName, FileAsset &fileAsset, bool &isContains)
658 {
659     fileAsset.SetDisplayName(displayName);
660     isContains = true;
661 }
662 
CreateV10(MediaLibraryCommand & cmd)663 int32_t MediaLibraryPhotoOperations::CreateV10(MediaLibraryCommand& cmd)
664 {
665     FileAsset fileAsset;
666     ValuesBucket &values = cmd.GetValueBucket();
667     string displayName;
668     string extention;
669     string title;
670     bool isContains = false;
671     bool isNeedGrant = false;
672     if (GetStringFromValuesBucket(values, PhotoColumn::MEDIA_NAME, displayName)) {
673         SetAssetDisplayName(displayName, fileAsset, isContains);
674         fileAsset.SetTimePending(UNCREATE_FILE_TIMEPENDING);
675     } else {
676         CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, ASSET_EXTENTION, extention), E_HAS_DB_ERROR);
677         isNeedGrant = true;
678         fileAsset.SetTimePending(UNOPEN_FILE_COMPONENT_TIMEPENDING);
679         if (GetStringFromValuesBucket(values, PhotoColumn::MEDIA_TITLE, title)) {
680             displayName = title + "." + extention;
681             SetAssetDisplayName(displayName, fileAsset, isContains);
682         }
683     }
684     int32_t mediaType = 0;
685     CHECK_AND_RETURN_RET(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_TYPE, mediaType), E_HAS_DB_ERROR);
686     fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
687     SetPhotoSubTypeFromCmd(cmd, fileAsset);
688     SetCameraShotKeyFromCmd(cmd, fileAsset);
689     SetCallingPackageName(cmd, fileAsset);
690     // Check rootdir and extention
691     int32_t errCode = CheckWithType(isContains, displayName, extention, mediaType);
692     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
693     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
694     int32_t outRow = -1;
695     std::function<int(void)> func = [&]()->int {
696         errCode = isContains ? SetAssetPathInCreate(fileAsset, trans) :
697             SetAssetPath(fileAsset, extention, trans);
698         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to Set Path, Name=%{private}s", displayName.c_str());
699         outRow = InsertAssetInDb(trans, cmd, fileAsset);
700         AuditLog auditLog = { true, "USER BEHAVIOR", "ADD", "io", 1, "running", "ok" };
701         HiAudit::GetInstance().Write(auditLog);
702         CHECK_AND_RETURN_RET_LOG(outRow > 0, E_HAS_DB_ERROR, "insert file in db failed, error = %{public}d", outRow);
703         fileAsset.SetId(outRow);
704         SolvePhotoAlbumInCreate(cmd, fileAsset);
705         return errCode;
706     };
707     errCode = trans->RetryTrans(func);
708     if (errCode != E_OK) {
709         MEDIA_ERR_LOG("CreateV10: trans retry fail!, ret:%{public}d", errCode);
710     }
711     string fileUri = CreateExtUriForV10Asset(fileAsset);
712     if (isNeedGrant) {
713         bool isMovingPhoto = fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO);
714         int32_t ret = GrantUriPermission(fileUri, cmd.GetBundleName(), fileAsset.GetPath(), isMovingPhoto);
715         CHECK_AND_RETURN_RET(ret == E_OK, ret);
716     }
717     cmd.SetResult(fileUri);
718     return outRow;
719 }
720 
DeletePhoto(const shared_ptr<FileAsset> & fileAsset,MediaLibraryApi api)721 int32_t MediaLibraryPhotoOperations::DeletePhoto(const shared_ptr<FileAsset> &fileAsset, MediaLibraryApi api)
722 {
723     string filePath = fileAsset->GetPath();
724     CHECK_AND_RETURN_RET_LOG(!filePath.empty(), E_INVALID_PATH, "get file path failed");
725     bool res = MediaFileUtils::DeleteFile(filePath);
726     CHECK_AND_RETURN_RET_LOG(res, E_HAS_FS_ERROR, "Delete photo file failed, errno: %{public}d", errno);
727 
728     // delete thumbnail
729     int32_t fileId = fileAsset->GetId();
730     InvalidateThumbnail(to_string(fileId), fileAsset->GetMediaType());
731 
732     string displayName = fileAsset->GetDisplayName();
733     // delete file in db
734     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::DELETE);
735     cmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::MEDIA_ID, to_string(fileId));
736     int32_t deleteRows = DeleteAssetInDb(cmd);
737     if (deleteRows <= 0) {
738         MEDIA_ERR_LOG("Delete photo in database failed, errCode=%{public}d", deleteRows);
739         return E_HAS_DB_ERROR;
740     }
741 
742     auto watch = MediaLibraryNotify::GetInstance();
743     string notifyDeleteUri =
744         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(deleteRows),
745         (api == MediaLibraryApi::API_10 ? MediaFileUtils::GetExtraUri(displayName, filePath) : ""));
746     watch->Notify(notifyDeleteUri, NotifyType::NOTIFY_REMOVE);
747 
748     DeleteRevertMessage(filePath);
749     return deleteRows;
750 }
751 
TrashPhotosSendNotify(vector<string> & notifyUris,shared_ptr<AlbumData> albumData)752 void MediaLibraryPhotoOperations::TrashPhotosSendNotify(vector<string> &notifyUris,
753     shared_ptr<AlbumData> albumData)
754 {
755     auto watch = MediaLibraryNotify::GetInstance();
756     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
757     if (trashAlbumId <= 0) {
758         return;
759     }
760     if (notifyUris.empty()) {
761         return;
762     }
763     if (notifyUris.size() == 1) {
764         if (albumData != nullptr && albumData->isHidden.size() != 0) {
765             watch->Notify(notifyUris[0], albumData->isHidden[0] ?
766                 NotifyType::NOTIFY_UPDATE : NotifyType::NOTIFY_REMOVE);
767         } else {
768             watch->Notify(notifyUris[0], NotifyType::NOTIFY_REMOVE);
769         }
770         watch->Notify(notifyUris[0], NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
771         watch->Notify(notifyUris[0], NotifyType::NOTIFY_ALBUM_ADD_ASSET, trashAlbumId);
772     } else {
773         watch->Notify(PhotoColumn::PHOTO_URI_PREFIX, NotifyType::NOTIFY_UPDATE);
774         watch->Notify(PhotoAlbumColumns::ALBUM_URI_PREFIX, NotifyType::NOTIFY_UPDATE);
775     }
776     vector<int64_t> formIds;
777     for (const auto &notifyUri : notifyUris) {
778         MediaLibraryFormMapOperations::GetFormMapFormId(notifyUri.c_str(), formIds);
779     }
780     if (!formIds.empty()) {
781         MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
782     }
783 }
784 
GetPhotoHiddenStatus(std::shared_ptr<AlbumData> data,const string & assetId)785 static void GetPhotoHiddenStatus(std::shared_ptr<AlbumData> data, const string& assetId)
786 {
787     if (data == nullptr) {
788         return;
789     }
790     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
791     const std::string queryAssetHiddenInfo = "SELECT hidden FROM Photos WHERE file_id = " + assetId;
792     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(queryAssetHiddenInfo);
793     if (resultSet == nullptr) {
794         return;
795     }
796     int32_t isHidden = 0;
797     if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
798         int32_t isHiddenIndex = -1;
799         resultSet->GetColumnIndex(MediaColumn::MEDIA_HIDDEN, isHiddenIndex);
800         if (resultSet->GetInt(isHiddenIndex, isHidden) != NativeRdb::E_OK) {
801             return;
802         }
803     }
804     data->isHidden.push_back(isHidden);
805     resultSet->Close();
806 }
807 
UpdateSourcePath(const vector<string> & whereArgs)808 void MediaLibraryPhotoOperations::UpdateSourcePath(const vector<string> &whereArgs)
809 {
810     const std::string sourcePathPrefix = "/storage/emulated/0";
811     if (whereArgs.empty()) {
812         MEDIA_WARN_LOG("whereArgs is empty");
813         return;
814     }
815 
816     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
817     for (auto assetId: whereArgs) {
818         const std::string QUERY_FILE_ASSET_INFO = "SELECT * FROM Photos WHERE file_id = " + assetId;
819         shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(QUERY_FILE_ASSET_INFO);
820         if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
821             MEDIA_ERR_LOG("Query not matched data fails on update source path");
822             continue;
823         }
824         int displayNameIndex = -1;
825         string displayName;
826         resultSet->GetColumnIndex(MediaColumn::MEDIA_NAME, displayNameIndex);
827         if (resultSet->GetString(displayNameIndex, displayName) != NativeRdb::E_OK) {
828             continue;
829         }
830         int ownerAlbumIdIndex;
831         int32_t ownerAlbumId;
832         resultSet->GetColumnIndex(PhotoColumn::PHOTO_OWNER_ALBUM_ID, ownerAlbumIdIndex);
833         if (resultSet->GetInt(ownerAlbumIdIndex, ownerAlbumId) != NativeRdb::E_OK) {
834             continue;
835         }
836         resultSet->Close();
837 
838         const std::string QUERY_LPATH_INFO = "SELECT * FROM PhotoAlbum WHERE album_id = " + to_string(ownerAlbumId);
839         shared_ptr<NativeRdb::ResultSet> resultSetAlbum = rdbStore->QuerySql(QUERY_LPATH_INFO);
840         if (resultSetAlbum == nullptr || resultSetAlbum->GoToFirstRow() != NativeRdb::E_OK) {
841             MEDIA_ERR_LOG("Query not matched data fails on update source path");
842             continue;
843         }
844         int lpathIndex;
845         string lpath;
846         resultSetAlbum->GetColumnIndex(PhotoAlbumColumns::ALBUM_LPATH, lpathIndex);
847         if (resultSetAlbum->GetString(lpathIndex, lpath) != NativeRdb::E_OK) {
848             continue;
849         }
850         resultSetAlbum->Close();
851 
852         string newSourcePath = sourcePathPrefix + lpath + "/" + displayName;
853         ValuesBucket values;
854         values.PutString(PhotoColumn::PHOTO_SOURCE_PATH, newSourcePath);
855         RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
856         predicates.EqualTo(MediaColumn::MEDIA_ID, assetId);
857         int32_t changedRows = 0;
858         rdbStore->Update(changedRows, values, predicates);
859     }
860 }
861 
TrashPhotos(MediaLibraryCommand & cmd)862 int32_t MediaLibraryPhotoOperations::TrashPhotos(MediaLibraryCommand &cmd)
863 {
864     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
865     if (rdbStore == nullptr) {
866         return E_HAS_DB_ERROR;
867     }
868 
869     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(cmd.GetDataSharePred(),
870         PhotoColumn::PHOTOS_TABLE);
871     vector<string> notifyUris = rdbPredicate.GetWhereArgs();
872     MediaLibraryRdbStore::ReplacePredicatesUriToId(rdbPredicate);
873 
874     MultiStagesCaptureManager::RemovePhotos(rdbPredicate, true);
875     UpdateSourcePath(rdbPredicate.GetWhereArgs());
876     std::shared_ptr<AlbumData> albumData = std::make_shared<AlbumData>();
877     if (!rdbPredicate.GetWhereArgs().empty()) {
878         GetPhotoHiddenStatus(albumData, rdbPredicate.GetWhereArgs()[0]);
879     }
880     ValuesBucket values;
881     values.Put(MediaColumn::MEDIA_DATE_TRASHED, MediaFileUtils::UTCTimeMilliSeconds());
882     cmd.SetValueBucket(values);
883     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, rdbPredicate);
884     if (updatedRows < 0) {
885         MEDIA_ERR_LOG("Trash photo failed. Result %{public}d.", updatedRows);
886         return E_HAS_DB_ERROR;
887     }
888     // delete cloud enhanacement task
889     vector<string> ids = rdbPredicate.GetWhereArgs();
890     vector<string> photoIds;
891     EnhancementManager::GetInstance().CancelTasksInternal(ids, photoIds, CloudEnhancementAvailableType::TRASH);
892     for (string& photoId : photoIds) {
893         CloudEnhancementGetCount::GetInstance().Report("DeleteCancellationType", photoId);
894     }
895     MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
896         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), notifyUris);
897     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, notifyUris, NotifyAlbumType::SYS_ALBUM);
898     if (static_cast<size_t>(updatedRows) != notifyUris.size()) {
899         MEDIA_WARN_LOG("Try to notify %{public}zu items, but only %{public}d items updated.",
900             notifyUris.size(), updatedRows);
901     }
902     TrashPhotosSendNotify(notifyUris, albumData);
903     DfxManager::GetInstance()->HandleDeleteBehavior(DfxType::TRASH_PHOTO, updatedRows, notifyUris);
904     return updatedRows;
905 }
906 
DiscardCameraPhoto(MediaLibraryCommand & cmd)907 static int32_t DiscardCameraPhoto(MediaLibraryCommand &cmd)
908 {
909     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(cmd.GetDataSharePred(),
910         PhotoColumn::PHOTOS_TABLE);
911     vector<string> notifyUris = rdbPredicate.GetWhereArgs();
912     MediaLibraryRdbStore::ReplacePredicatesUriToId(rdbPredicate);
913     return MediaLibraryAssetOperations::DeleteFromDisk(rdbPredicate, false, true);
914 }
915 
GetUriWithoutSeg(const string & oldUri)916 static string GetUriWithoutSeg(const string &oldUri)
917 {
918     size_t questionMaskPoint = oldUri.rfind('?');
919     if (questionMaskPoint != string::npos) {
920         return oldUri.substr(0, questionMaskPoint);
921     }
922     return oldUri;
923 }
924 
UpdateDirtyWithoutIsTemp(RdbPredicates & predicates)925 static int32_t UpdateDirtyWithoutIsTemp(RdbPredicates &predicates)
926 {
927     ValuesBucket valuesBucketDirty;
928     valuesBucketDirty.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
929     int32_t updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(valuesBucketDirty, predicates);
930     return updateDirtyRows;
931 }
932 
UpdateIsTempAndDirty(MediaLibraryCommand & cmd,const string & fileId)933 static int32_t UpdateIsTempAndDirty(MediaLibraryCommand &cmd, const string &fileId)
934 {
935     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
936     predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
937     ValuesBucket values;
938     values.Put(PhotoColumn::PHOTO_IS_TEMP, false);
939 
940     int32_t updateDirtyRows = 0;
941     if (cmd.GetQuerySetParam(PhotoColumn::PHOTO_DIRTY) == to_string(static_cast<int32_t>(DirtyType::TYPE_NEW))) {
942         // Only third-party app save photo, it will bring dirty flag
943         // The photo saved by third-party apps, whether of low or high quality, should set dirty to TYPE_NEW
944         // Every subtype of photo saved by third-party apps, should set dirty to TYPE_NEW
945         // Need to change the quality to high quality before updating
946         values.Put(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
947         values.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
948         updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
949         if (updateDirtyRows < 0) {
950             MEDIA_ERR_LOG("update third party photo temp and dirty flag fail.");
951             return E_ERR;
952         }
953         return updateDirtyRows;
954     }
955 
956     string subTypeStr = cmd.GetQuerySetParam(PhotoColumn::PHOTO_SUBTYPE);
957     if (subTypeStr.empty()) {
958         MEDIA_ERR_LOG("get subType fail");
959         return E_ERR;
960     }
961     int32_t subType = stoi(subTypeStr);
962     if (subType == static_cast<int32_t>(PhotoSubType::BURST)) {
963         predicates.EqualTo(PhotoColumn::PHOTO_QUALITY, to_string(static_cast<int32_t>(MultiStagesPhotoQuality::FULL)));
964         predicates.EqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::BURST)));
965         values.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
966         updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
967         if (updateDirtyRows < 0) {
968             MEDIA_ERR_LOG("burst photo update temp and dirty flag fail.");
969             return E_ERR;
970         }
971         return updateDirtyRows;
972     }
973 
974     int32_t updateIsTempRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
975     if (updateIsTempRows < 0) {
976         MEDIA_ERR_LOG("update temp flag fail.");
977         return E_ERR;
978     }
979     if (subType != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
980         predicates.EqualTo(PhotoColumn::PHOTO_QUALITY, to_string(static_cast<int32_t>(MultiStagesPhotoQuality::FULL)));
981         predicates.NotEqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)));
982         updateDirtyRows = UpdateDirtyWithoutIsTemp(predicates);
983         if (updateDirtyRows < 0) {
984             MEDIA_ERR_LOG("update dirty flag fail.");
985             return E_ERR;
986         }
987     }
988     return updateDirtyRows;
989 }
990 
SaveCameraPhoto(MediaLibraryCommand & cmd)991 int32_t MediaLibraryPhotoOperations::SaveCameraPhoto(MediaLibraryCommand &cmd)
992 {
993     MediaLibraryTracer tracer;
994     tracer.Start("MediaLibraryPhotoOperations::SaveCameraPhoto");
995     string fileId = cmd.GetQuerySetParam(PhotoColumn::MEDIA_ID);
996     if (fileId.empty()) {
997         MEDIA_ERR_LOG("SaveCameraPhoto, get fileId fail");
998         return 0;
999     }
1000     MEDIA_INFO_LOG("start SaveCameraPhoto, fileId: %{public}s", fileId.c_str());
1001     int32_t ret = UpdateIsTempAndDirty(cmd, fileId);
1002     if (ret < 0) {
1003         return 0;
1004     }
1005     string fileType = cmd.GetQuerySetParam(IMAGE_FILE_TYPE);
1006     if (!fileType.empty()) {
1007         SavePicture(stoi(fileType), stoi(fileId));
1008     }
1009 
1010     string needScanStr = cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD);
1011     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, fileId,
1012                                                          OperationObject::FILESYSTEM_PHOTO, PHOTO_COLUMN_VECTOR);
1013     if (fileAsset == nullptr) {
1014         MEDIA_ERR_LOG("SaveCameraPhoto, get fileAsset fail");
1015         return 0;
1016     }
1017     std::string path = fileAsset->GetPath();
1018     int32_t burstCoverLevel = fileAsset->GetBurstCoverLevel();
1019     if (!path.empty()) {
1020         if (burstCoverLevel == static_cast<int32_t>(BurstCoverLevelType::COVER)) {
1021             ScanFile(path, false, true, true, stoi(fileId));
1022         } else {
1023             MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(path, false, true, true, stoi(fileId));
1024         }
1025     }
1026     MEDIA_INFO_LOG("Success, ret: %{public}d, needScanStr: %{public}s", ret, needScanStr.c_str());
1027     return ret;
1028 }
1029 
SetVideoEnhancementAttr(MediaLibraryCommand & cmd)1030 int32_t MediaLibraryPhotoOperations::SetVideoEnhancementAttr(MediaLibraryCommand &cmd)
1031 {
1032     string videoId = cmd.GetQuerySetParam(PhotoColumn::PHOTO_ID);
1033     string fileId = cmd.GetQuerySetParam(MediaColumn::MEDIA_ID);
1034     string filePath = cmd.GetQuerySetParam(MediaColumn::MEDIA_FILE_PATH);
1035     MultiStagesVideoCaptureManager::GetInstance().AddVideo(videoId, fileId, filePath);
1036     return E_OK;
1037 }
1038 
GetHiddenState(const ValuesBucket & values)1039 static int32_t GetHiddenState(const ValuesBucket &values)
1040 {
1041     ValueObject obj;
1042     auto ret = values.GetObject(MediaColumn::MEDIA_HIDDEN, obj);
1043     if (!ret) {
1044         return E_INVALID_VALUES;
1045     }
1046     int32_t hiddenState = 0;
1047     ret = obj.GetInt(hiddenState);
1048     if (ret != E_OK) {
1049         return E_INVALID_VALUES;
1050     }
1051     return hiddenState == 0 ? 0 : 1;
1052 }
1053 
SendHideNotify(vector<string> & notifyUris,const int32_t hiddenState)1054 static void SendHideNotify(vector<string> &notifyUris, const int32_t hiddenState)
1055 {
1056     auto watch = MediaLibraryNotify::GetInstance();
1057     if (watch == nullptr) {
1058         return;
1059     }
1060     int hiddenAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::HIDDEN);
1061     if (hiddenAlbumId <= 0) {
1062         return;
1063     }
1064 
1065     NotifyType assetNotifyType;
1066     NotifyType albumNotifyType;
1067     NotifyType hiddenAlbumNotifyType;
1068     if (hiddenState > 0) {
1069         assetNotifyType = NotifyType::NOTIFY_REMOVE;
1070         albumNotifyType = NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1071         hiddenAlbumNotifyType = NotifyType::NOTIFY_ALBUM_ADD_ASSET;
1072     } else {
1073         assetNotifyType = NotifyType::NOTIFY_ADD;
1074         albumNotifyType = NotifyType::NOTIFY_ALBUM_ADD_ASSET;
1075         hiddenAlbumNotifyType = NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1076     }
1077     vector<int64_t> formIds;
1078     for (const auto &notifyUri : notifyUris) {
1079         watch->Notify(notifyUri, assetNotifyType);
1080         watch->Notify(notifyUri, albumNotifyType, 0, true);
1081         watch->Notify(notifyUri, hiddenAlbumNotifyType, hiddenAlbumId);
1082         if (!hiddenState) {
1083             watch->Notify(notifyUri, NotifyType::NOTIFY_THUMB_ADD);
1084         }
1085         MediaLibraryFormMapOperations::GetFormMapFormId(notifyUri.c_str(), formIds);
1086     }
1087     if (!formIds.empty()) {
1088         MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
1089     }
1090 }
1091 
HidePhotos(MediaLibraryCommand & cmd)1092 static int32_t HidePhotos(MediaLibraryCommand &cmd)
1093 {
1094     int32_t hiddenState = GetHiddenState(cmd.GetValueBucket());
1095     if (hiddenState < 0) {
1096         return hiddenState;
1097     }
1098 
1099     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
1100     vector<string> notifyUris = predicates.GetWhereArgs();
1101     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
1102     if (hiddenState != 0) {
1103         MediaLibraryPhotoOperations::UpdateSourcePath(predicates.GetWhereArgs());
1104     } else {
1105         MediaLibraryAlbumOperations::DealwithNoAlbumAssets(predicates.GetWhereArgs());
1106     }
1107     ValuesBucket values;
1108     values.Put(MediaColumn::MEDIA_HIDDEN, hiddenState);
1109     if (predicates.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
1110         values.PutLong(PhotoColumn::PHOTO_HIDDEN_TIME,
1111             hiddenState ? MediaFileUtils::UTCTimeMilliSeconds() : 0);
1112     }
1113     int32_t changedRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1114     if (changedRows < 0) {
1115         return changedRows;
1116     }
1117     MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
1118         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), notifyUris);
1119     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1120     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, notifyUris, NotifyAlbumType::SYS_ALBUM);
1121     SendHideNotify(notifyUris, hiddenState);
1122     return changedRows;
1123 }
1124 
GetFavoriteState(const ValuesBucket & values)1125 static int32_t GetFavoriteState(const ValuesBucket& values)
1126 {
1127     ValueObject obj;
1128     bool isValid = values.GetObject(PhotoColumn::MEDIA_IS_FAV, obj);
1129     if (!isValid) {
1130         return E_INVALID_VALUES;
1131     }
1132 
1133     int32_t favoriteState = -1;
1134     int ret = obj.GetInt(favoriteState);
1135     if (ret != E_OK || (favoriteState != 0 && favoriteState != 1)) {
1136         return E_INVALID_VALUES;
1137     }
1138     return favoriteState;
1139 }
1140 
BatchSetFavorite(MediaLibraryCommand & cmd)1141 static int32_t BatchSetFavorite(MediaLibraryCommand& cmd)
1142 {
1143     int32_t favoriteState = GetFavoriteState(cmd.GetValueBucket());
1144     CHECK_AND_RETURN_RET_LOG(favoriteState >= 0, favoriteState, "Failed to get favoriteState");
1145     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1146     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore");
1147 
1148     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
1149     vector<string> notifyUris = predicates.GetWhereArgs();
1150     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
1151     ValuesBucket values;
1152     values.Put(PhotoColumn::MEDIA_IS_FAV, favoriteState);
1153     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, predicates);
1154     CHECK_AND_RETURN_RET_LOG(updatedRows >= 0, E_HAS_DB_ERROR, "Failed to set favorite, err: %{public}d", updatedRows);
1155 
1156     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
1157     MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
1158 
1159     auto watch = MediaLibraryNotify::GetInstance();
1160     int favAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE);
1161     if (favAlbumId > 0) {
1162         NotifyType type = favoriteState ? NotifyType::NOTIFY_ALBUM_ADD_ASSET : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1163         for (const string& notifyUri : notifyUris) {
1164             watch->Notify(notifyUri, type, favAlbumId);
1165         }
1166     } else {
1167         MEDIA_WARN_LOG("Favorite album not found, failed to notify favorite album.");
1168     }
1169 
1170     for (const string& notifyUri : notifyUris) {
1171         watch->Notify(notifyUri, NotifyType::NOTIFY_UPDATE);
1172     }
1173 
1174     if (static_cast<size_t>(updatedRows) != notifyUris.size()) {
1175         MEDIA_WARN_LOG(
1176             "Try to notify %{public}zu items, but only %{public}d items updated.", notifyUris.size(), updatedRows);
1177     }
1178     return updatedRows;
1179 }
1180 
BatchSetUserComment(MediaLibraryCommand & cmd)1181 int32_t MediaLibraryPhotoOperations::BatchSetUserComment(MediaLibraryCommand& cmd)
1182 {
1183     vector<shared_ptr<FileAsset>> fileAssetVector;
1184     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH,
1185         PhotoColumn::MEDIA_TYPE, PhotoColumn::MEDIA_NAME };
1186     MediaLibraryRdbStore::ReplacePredicatesUriToId(*(cmd.GetAbsRdbPredicates()));
1187     int32_t errCode = GetFileAssetVectorFromDb(*(cmd.GetAbsRdbPredicates()),
1188         OperationObject::FILESYSTEM_PHOTO, fileAssetVector, columns);
1189     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1190         "Failed to query file asset vector from db, errCode=%{private}d", errCode);
1191 
1192     for (const auto& fileAsset : fileAssetVector) {
1193         errCode = SetUserComment(cmd, fileAsset);
1194         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to set user comment, errCode=%{private}d", errCode);
1195     }
1196 
1197     int32_t updateRows = UpdateFileInDb(cmd);
1198     if (updateRows < 0) {
1199         MEDIA_ERR_LOG("Update Photo in database failed, updateRows=%{public}d", updateRows);
1200         return updateRows;
1201     }
1202 
1203     auto watch = MediaLibraryNotify::GetInstance();
1204     for (const auto& fileAsset : fileAssetVector) {
1205         string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath());
1206         string assetUri = MediaFileUtils::GetUriByExtrConditions(
1207             PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri);
1208         watch->Notify(assetUri, NotifyType::NOTIFY_UPDATE);
1209     }
1210     return updateRows;
1211 }
1212 
UpdateExif(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1213 int32_t MediaLibraryPhotoOperations::UpdateExif(MediaLibraryCommand &cmd,
1214     const shared_ptr<FileAsset> &fileAsset)
1215 {
1216     if (fileAsset == nullptr) {
1217         MEDIA_ERR_LOG("fileAsset is null");
1218         return E_INVALID_VALUES;
1219     }
1220     ValuesBucket &values = cmd.GetValueBucket();
1221     ValueObject valueObject;
1222     int32_t hasOrientation = values.GetObject(PhotoColumn::PHOTO_ORIENTATION, valueObject);
1223     int32_t errCode = E_OK;
1224     if (hasOrientation) {
1225         if (fileAsset->GetMediaType() != MEDIA_TYPE_IMAGE) {
1226             MEDIA_ERR_LOG("Only images support rotation.");
1227             return E_INVALID_VALUES;
1228         }
1229         errCode = UpdateAllExif(cmd, fileAsset);
1230     } else {
1231         CHECK_AND_RETURN_RET_LOG(false, errCode, "The image does not have rotation angle: %{public}d", errCode);
1232     }
1233     return errCode;
1234 }
1235 
UpdateAlbumOnSystemMoveAssets(const int32_t & oriAlbumId,const int32_t & targetAlbumId)1236 void UpdateAlbumOnSystemMoveAssets(const int32_t &oriAlbumId, const int32_t &targetAlbumId)
1237 {
1238     MediaLibraryRdbUtils::UpdateUserAlbumInternal(
1239         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(),
1240         { to_string(oriAlbumId), to_string(targetAlbumId) });
1241     MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
1242         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(),
1243         { to_string(oriAlbumId), to_string(targetAlbumId) });
1244 }
1245 
IsSystemAlbumMovement(MediaLibraryCommand & cmd)1246 bool IsSystemAlbumMovement(MediaLibraryCommand &cmd)
1247 {
1248     auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
1249     auto whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
1250     int32_t oriAlbumId = MediaLibraryAssetOperations::GetAlbumIdByPredicates(whereClause, whereArgs);
1251     PhotoAlbumType type;
1252     PhotoAlbumSubType subType;
1253     CHECK_AND_RETURN_RET_LOG(GetAlbumTypeSubTypeById(to_string(oriAlbumId), type, subType) == E_SUCCESS, false,
1254         "move assets invalid album uri");
1255     if ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType))) {
1256         MEDIA_ERR_LOG("album id %{private}s type:%d subtype:%d", to_string(oriAlbumId).c_str(), type, subType);
1257         return false;
1258     }
1259 
1260     return type == PhotoAlbumType::SYSTEM;
1261 }
1262 
GetSystemMoveAssets(AbsRdbPredicates & predicates)1263 void GetSystemMoveAssets(AbsRdbPredicates &predicates)
1264 {
1265     const vector<string> &whereUriArgs = predicates.GetWhereArgs();
1266     if (whereUriArgs.size() <= 1) {
1267         MEDIA_ERR_LOG("Move vector empty when move from system album");
1268         return;
1269     }
1270     vector<string> whereIdArgs;
1271     whereIdArgs.reserve(whereUriArgs.size() - 1);
1272     for (size_t i = 1; i < whereUriArgs.size(); ++i) {
1273         whereIdArgs.push_back(whereUriArgs[i]);
1274     }
1275     predicates.SetWhereArgs(whereIdArgs);
1276 }
1277 
PrepareUpdateArgs(MediaLibraryCommand & cmd,std::map<int32_t,std::vector<int32_t>> & ownerAlbumIds,vector<string> & assetString,RdbPredicates & predicates)1278 int32_t PrepareUpdateArgs(MediaLibraryCommand &cmd, std::map<int32_t, std::vector<int32_t>> &ownerAlbumIds,
1279     vector<string> &assetString, RdbPredicates &predicates)
1280 {
1281     auto assetVector = cmd.GetAbsRdbPredicates()->GetWhereArgs();
1282     for (const auto &fileAsset : assetVector) {
1283         assetString.push_back(fileAsset);
1284     }
1285 
1286     predicates.And()->In(PhotoColumn::MEDIA_ID, assetString);
1287     vector<string> columns = { PhotoColumn::PHOTO_OWNER_ALBUM_ID, PhotoColumn::MEDIA_ID };
1288     auto resultSetQuery = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
1289     if (resultSetQuery == nullptr) {
1290         MEDIA_ERR_LOG("album id is not exist");
1291         return E_INVALID_ARGUMENTS;
1292     }
1293     while (resultSetQuery->GoToNextRow() == NativeRdb::E_OK) {
1294         int32_t albumId = 0;
1295         albumId = GetInt32Val(PhotoColumn::PHOTO_OWNER_ALBUM_ID, resultSetQuery);
1296         ownerAlbumIds[albumId].push_back(GetInt32Val(MediaColumn::MEDIA_ID, resultSetQuery));
1297     }
1298     resultSetQuery->Close();
1299     return E_OK;
1300 }
1301 
UpdateSystemRows(MediaLibraryCommand & cmd)1302 int32_t UpdateSystemRows(MediaLibraryCommand &cmd)
1303 {
1304     std::map<int32_t, std::vector<int32_t>> ownerAlbumIds;
1305     vector<string> assetString;
1306     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1307     if (PrepareUpdateArgs(cmd, ownerAlbumIds, assetString, predicates) != E_OK) {
1308         return E_INVALID_ARGUMENTS;
1309     }
1310 
1311     ValueObject value;
1312     int32_t targetAlbumId = 0;
1313     if (!cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, value)) {
1314         MEDIA_ERR_LOG("get owner album id fail when move from system album");
1315         return E_INVALID_ARGUMENTS;
1316     }
1317     value.GetInt(targetAlbumId);
1318     ValuesBucket values;
1319     values.Put(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(targetAlbumId));
1320     int32_t changedRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1321     if (changedRows < 0) {
1322         MEDIA_ERR_LOG("Update owner album id fail when move from system album");
1323         return changedRows;
1324     }
1325     for (auto it = ownerAlbumIds.begin(); it != ownerAlbumIds.end(); it++) {
1326         MEDIA_INFO_LOG("System album move assets target album id is: %{public}s", to_string(it->first).c_str());
1327         int32_t oriAlbumId = it->first;
1328         UpdateAlbumOnSystemMoveAssets(oriAlbumId, targetAlbumId);
1329         auto watch = MediaLibraryNotify::GetInstance();
1330         for (const auto &id : it->second) {
1331             watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(id),
1332                 NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, oriAlbumId);
1333             watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(id),
1334                 NotifyType::NOTIFY_ALBUM_ADD_ASSET, targetAlbumId);
1335         }
1336     }
1337     return changedRows;
1338 }
1339 
BatchSetOwnerAlbumId(MediaLibraryCommand & cmd)1340 int32_t MediaLibraryPhotoOperations::BatchSetOwnerAlbumId(MediaLibraryCommand &cmd)
1341 {
1342     vector<shared_ptr<FileAsset>> fileAssetVector;
1343     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH,
1344         PhotoColumn::MEDIA_TYPE, PhotoColumn::MEDIA_NAME };
1345     MediaLibraryRdbStore::ReplacePredicatesUriToId(*(cmd.GetAbsRdbPredicates()));
1346 
1347     // Check if move from system album
1348     if (IsSystemAlbumMovement(cmd)) {
1349         MEDIA_INFO_LOG("Move assets from system album");
1350         GetSystemMoveAssets(*(cmd.GetAbsRdbPredicates()));
1351         int32_t updateSysRows = UpdateSystemRows(cmd);
1352         return updateSysRows;
1353     }
1354 
1355     int32_t errCode = GetFileAssetVectorFromDb(*(cmd.GetAbsRdbPredicates()),
1356         OperationObject::FILESYSTEM_PHOTO, fileAssetVector, columns);
1357     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1358         "Failed to query file asset vector from db, errCode=%{private}d", errCode);
1359     int32_t updateRows = UpdateFileInDb(cmd);
1360     if (updateRows < 0) {
1361         MEDIA_ERR_LOG("Update Photo in database failed, updateRows=%{public}d", updateRows);
1362         return updateRows;
1363     }
1364     int32_t targetAlbumId = 0;
1365     int32_t oriAlbumId = 0;
1366     UpdateOwnerAlbumIdOnMove(cmd, targetAlbumId, oriAlbumId);
1367     auto watch =  MediaLibraryNotify::GetInstance();
1368     for (const auto &fileAsset : fileAssetVector) {
1369         string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath());
1370         string assetUri = MediaFileUtils::GetUriByExtrConditions(
1371             PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri);
1372         watch->Notify(assetUri, NotifyType::NOTIFY_UPDATE);
1373         watch->Notify(assetUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET, targetAlbumId);
1374         watch->Notify(assetUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, oriAlbumId);
1375     }
1376     return updateRows;
1377 }
1378 
UpdateFileAsset(MediaLibraryCommand & cmd)1379 int32_t MediaLibraryPhotoOperations::UpdateFileAsset(MediaLibraryCommand &cmd)
1380 {
1381     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_TYPE,
1382         PhotoColumn::MEDIA_NAME, PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::PHOTO_EDIT_TIME, MediaColumn::MEDIA_HIDDEN,
1383         PhotoColumn::MOVING_PHOTO_EFFECT_MODE };
1384     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
1385         OperationObject::FILESYSTEM_PHOTO, columns);
1386     if (fileAsset == nullptr) {
1387         return E_INVALID_VALUES;
1388     }
1389 
1390     bool isNeedScan = false;
1391     int32_t errCode = RevertToOriginalEffectMode(cmd, fileAsset, isNeedScan);
1392     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to revert original effect mode: %{public}d", errCode);
1393     if (cmd.GetOprnType() == OperationType::SET_USER_COMMENT) {
1394         errCode = SetUserComment(cmd, fileAsset);
1395         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Edit user comment errCode = %{private}d", errCode);
1396     }
1397 
1398     // Update if FileAsset.title or FileAsset.displayName is modified
1399     bool isNameChanged = false;
1400     errCode = UpdateFileName(cmd, fileAsset, isNameChanged);
1401     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update Photo Name failed, fileName=%{private}s",
1402         fileAsset->GetDisplayName().c_str());
1403 
1404     int32_t rowId = UpdateFileInDb(cmd);
1405     if (rowId < 0) {
1406         MEDIA_ERR_LOG("Update Photo In database failed, rowId=%{public}d", rowId);
1407         return rowId;
1408     }
1409     string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath());
1410     errCode = SendTrashNotify(cmd, fileAsset->GetId(), extraUri);
1411     if (errCode == E_OK) {
1412         return rowId;
1413     }
1414     SendFavoriteNotify(cmd, fileAsset, extraUri);
1415     SendModifyUserCommentNotify(cmd, fileAsset->GetId(), extraUri);
1416 
1417     if (isNeedScan) {
1418         ScanFile(fileAsset->GetPath(), true, true, true);
1419         return rowId;
1420     }
1421     auto watch = MediaLibraryNotify::GetInstance();
1422     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()),
1423         extraUri), NotifyType::NOTIFY_UPDATE);
1424     return rowId;
1425 }
1426 
UpdateV10(MediaLibraryCommand & cmd)1427 int32_t MediaLibraryPhotoOperations::UpdateV10(MediaLibraryCommand &cmd)
1428 {
1429     switch (cmd.GetOprnType()) {
1430         case OperationType::TRASH_PHOTO:
1431             return TrashPhotos(cmd);
1432         case OperationType::UPDATE_PENDING:
1433             return SetPendingStatus(cmd);
1434         case OperationType::HIDE:
1435             return HidePhotos(cmd);
1436         case OperationType::BATCH_UPDATE_FAV:
1437             return BatchSetFavorite(cmd);
1438         case OperationType::BATCH_UPDATE_USER_COMMENT:
1439             return BatchSetUserComment(cmd);
1440         case OperationType::BATCH_UPDATE_OWNER_ALBUM_ID:
1441             return BatchSetOwnerAlbumId(cmd);
1442         case OperationType::DISCARD_CAMERA_PHOTO:
1443             return DiscardCameraPhoto(cmd);
1444         case OperationType::SAVE_CAMERA_PHOTO:
1445             return SaveCameraPhoto(cmd);
1446         case OperationType::SET_VIDEO_ENHANCEMENT_ATTR:
1447             return SetVideoEnhancementAttr(cmd);
1448         case OperationType::SAVE_PICTURE:
1449             return ForceSavePicture(cmd);
1450         case OperationType::DEGENERATE_MOVING_PHOTO:
1451             return DegenerateMovingPhoto(cmd);
1452         case OperationType::SET_OWNER_ALBUM_ID:
1453             return UpdateOwnerAlbumId(cmd);
1454         default:
1455             return UpdateFileAsset(cmd);
1456     }
1457     return E_OK;
1458 }
1459 
UpdateV9(MediaLibraryCommand & cmd)1460 int32_t MediaLibraryPhotoOperations::UpdateV9(MediaLibraryCommand &cmd)
1461 {
1462     vector<string> columns = {
1463         PhotoColumn::MEDIA_ID,
1464         PhotoColumn::MEDIA_FILE_PATH,
1465         PhotoColumn::MEDIA_TYPE,
1466         PhotoColumn::MEDIA_NAME,
1467         PhotoColumn::MEDIA_RELATIVE_PATH,
1468         MediaColumn::MEDIA_HIDDEN
1469     };
1470     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
1471         OperationObject::FILESYSTEM_PHOTO, columns);
1472     if (fileAsset == nullptr) {
1473         return E_INVALID_VALUES;
1474     }
1475 
1476     // Update if FileAsset.title or FileAsset.displayName is modified
1477     bool isNameChanged = false;
1478     int32_t errCode = UpdateFileName(cmd, fileAsset, isNameChanged);
1479     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update Photo Name failed, fileName=%{private}s",
1480         fileAsset->GetDisplayName().c_str());
1481     errCode = UpdateRelativePath(cmd, fileAsset, isNameChanged);
1482     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update Photo RelativePath failed, relativePath=%{private}s",
1483         fileAsset->GetRelativePath().c_str());
1484     if (isNameChanged) {
1485         UpdateVirtualPath(cmd, fileAsset);
1486     }
1487 
1488     int32_t rowId = UpdateFileInDb(cmd);
1489     if (rowId < 0) {
1490         MEDIA_ERR_LOG("Update Photo In database failed, rowId=%{public}d", rowId);
1491         return rowId;
1492     }
1493 
1494     errCode = SendTrashNotify(cmd, fileAsset->GetId());
1495     if (errCode == E_OK) {
1496         return rowId;
1497     }
1498     SendFavoriteNotify(cmd, fileAsset);
1499     auto watch = MediaLibraryNotify::GetInstance();
1500     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId())),
1501         NotifyType::NOTIFY_UPDATE);
1502     return rowId;
1503 }
1504 
OpenCache(MediaLibraryCommand & cmd,const string & mode,bool & isCacheOperation)1505 int32_t MediaLibraryPhotoOperations::OpenCache(MediaLibraryCommand& cmd, const string& mode, bool& isCacheOperation)
1506 {
1507     isCacheOperation = false;
1508     string uriString = cmd.GetUriStringWithoutSegment();
1509     if (!MediaFileUtils::StartsWith(uriString, PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
1510         return E_OK;
1511     }
1512 
1513     isCacheOperation = true;
1514     string fileName = uriString.substr(PhotoColumn::PHOTO_CACHE_URI_PREFIX.size());
1515     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckDisplayName(fileName) == E_OK, E_INVALID_URI,
1516         "Check fileName failed, fileName=%{private}s", fileName.c_str());
1517     MediaType mediaType = MediaFileUtils::GetMediaType(fileName);
1518     CHECK_AND_RETURN_RET_LOG(mediaType == MediaType::MEDIA_TYPE_IMAGE || mediaType == MediaType::MEDIA_TYPE_VIDEO,
1519         E_INVALID_URI, "Check mediaType failed, fileName=%{private}s, mediaType=%{public}d", fileName.c_str(),
1520         mediaType);
1521 
1522     string cacheDir = GetAssetCacheDir();
1523     string path = cacheDir + "/" + fileName;
1524     string fileId = MediaFileUtils::GetIdFromUri(uriString);
1525 
1526     if (mode == MEDIA_FILEMODE_READONLY) {
1527         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(path), E_HAS_FS_ERROR,
1528             "Cache file does not exist, path=%{private}s", path.c_str());
1529         return OpenFileWithPrivacy(path, mode, fileId);
1530     }
1531     CHECK_AND_RETURN_RET_LOG(
1532         MediaFileUtils::CreateDirectory(cacheDir), E_HAS_FS_ERROR, "Cannot create dir %{private}s", cacheDir.c_str());
1533     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateAsset(path) == E_SUCCESS, E_HAS_FS_ERROR,
1534         "Create cache file failed, path=%{private}s", path.c_str());
1535     return OpenFileWithPrivacy(path, mode, fileId);
1536 }
1537 
OpenEditOperation(MediaLibraryCommand & cmd,bool & isSkip)1538 int32_t MediaLibraryPhotoOperations::OpenEditOperation(MediaLibraryCommand &cmd, bool &isSkip)
1539 {
1540     isSkip = true;
1541     string operationKey = cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD);
1542     if (operationKey.empty()) {
1543         return E_OK;
1544     }
1545     if (operationKey == EDIT_DATA_REQUEST) {
1546         isSkip = false;
1547         return RequestEditData(cmd);
1548     } else if (operationKey == SOURCE_REQUEST) {
1549         isSkip = false;
1550         return RequestEditSource(cmd);
1551     } else if (operationKey == COMMIT_REQUEST) {
1552         isSkip = false;
1553         return CommitEditOpen(cmd);
1554     }
1555 
1556     return E_OK;
1557 }
1558 
1559 const static vector<string> EDITED_COLUMN_VECTOR = {
1560     PhotoColumn::MEDIA_FILE_PATH,
1561     PhotoColumn::MEDIA_NAME,
1562     PhotoColumn::PHOTO_EDIT_TIME,
1563     PhotoColumn::MEDIA_TIME_PENDING,
1564     PhotoColumn::MEDIA_DATE_TRASHED,
1565     PhotoColumn::PHOTO_SUBTYPE,
1566     PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
1567     PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
1568 };
1569 
CheckFileAssetStatus(const shared_ptr<FileAsset> & fileAsset,bool checkMovingPhoto=false)1570 static int32_t CheckFileAssetStatus(const shared_ptr<FileAsset>& fileAsset, bool checkMovingPhoto = false)
1571 {
1572     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_URI, "FileAsset is nullptr");
1573     CHECK_AND_RETURN_RET_LOG(fileAsset->GetDateTrashed() == 0, E_IS_RECYCLED, "FileAsset is in recycle");
1574     CHECK_AND_RETURN_RET_LOG(fileAsset->GetTimePending() == 0, E_IS_PENDING_ERROR, "FileAsset is in pending");
1575     if (checkMovingPhoto) {
1576         CHECK_AND_RETURN_RET_LOG((fileAsset->GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) ||
1577             fileAsset->GetMovingPhotoEffectMode() == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)),
1578             E_INVALID_VALUES, "FileAsset is not moving photo");
1579     }
1580     return E_OK;
1581 }
1582 
RequestEditData(MediaLibraryCommand & cmd)1583 int32_t MediaLibraryPhotoOperations::RequestEditData(MediaLibraryCommand &cmd)
1584 {
1585     string uriString = cmd.GetUriStringWithoutSegment();
1586     string id = MediaFileUtils::GetIdFromUri(uriString);
1587     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
1588         return E_INVALID_URI;
1589     }
1590 
1591     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, id,
1592         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1593     int32_t err = CheckFileAssetStatus(fileAsset);
1594     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "Failed to check status of fileAsset: %{private}s", uriString.c_str());
1595 
1596     string path = fileAsset->GetFilePath();
1597     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI, "Can not get file path, uri=%{private}s",
1598         uriString.c_str());
1599 
1600     string editDataPath = GetEditDataPath(path);
1601     string dataPath = editDataPath;
1602     if (!MediaFileUtils::IsFileExists(dataPath)) {
1603         dataPath = GetEditDataCameraPath(path);
1604     }
1605     CHECK_AND_RETURN_RET_LOG(!dataPath.empty(), E_INVALID_PATH, "Get edit data path from path %{private}s failed",
1606         dataPath.c_str());
1607     if (fileAsset->GetPhotoEditTime() == 0 && !MediaFileUtils::IsFileExists(dataPath)) {
1608         MEDIA_INFO_LOG("File %{private}s does not have edit data", uriString.c_str());
1609         dataPath = editDataPath;
1610         string dataPathDir = GetEditDataDirPath(path);
1611         CHECK_AND_RETURN_RET_LOG(!dataPathDir.empty(), E_INVALID_PATH,
1612             "Get edit data dir path from path %{private}s failed", path.c_str());
1613         if (!MediaFileUtils::IsDirectory(dataPathDir)) {
1614             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dataPathDir), E_HAS_FS_ERROR,
1615                 "Failed to create dir %{private}s", dataPathDir.c_str());
1616         }
1617         err = MediaFileUtils::CreateAsset(dataPath);
1618         CHECK_AND_RETURN_RET_LOG(err == E_SUCCESS || err == E_FILE_EXIST, E_HAS_FS_ERROR,
1619             "Failed to create file %{private}s", dataPath.c_str());
1620     } else {
1621         if (!MediaFileUtils::IsFileExists(dataPath)) {
1622             MEDIA_INFO_LOG("File %{public}s has edit at %{public}ld, but cannot get editdata", uriString.c_str(),
1623                 (long)fileAsset->GetPhotoEditTime());
1624             return E_HAS_FS_ERROR;
1625         }
1626     }
1627 
1628     return OpenFileWithPrivacy(dataPath, "r", id);
1629 }
1630 
RequestEditSource(MediaLibraryCommand & cmd)1631 int32_t MediaLibraryPhotoOperations::RequestEditSource(MediaLibraryCommand &cmd)
1632 {
1633     string uriString = cmd.GetUriStringWithoutSegment();
1634     string id = MediaFileUtils::GetIdFromUri(uriString);
1635     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
1636         return E_INVALID_URI;
1637     }
1638     CHECK_AND_RETURN_RET_LOG(!PhotoEditingRecord::GetInstance()->IsInRevertOperation(stoi(id)),
1639         E_IS_IN_COMMIT, "File %{public}s is in revert, can not request source", id.c_str());
1640     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, id,
1641         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1642     int32_t err = CheckFileAssetStatus(fileAsset);
1643     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "Failed to check status of fileAsset: %{private}s", uriString.c_str());
1644     string path = fileAsset->GetFilePath();
1645     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI,
1646         "Can not get file path, uri=%{private}s", uriString.c_str());
1647     string movingPhotoVideoPath = "";
1648     bool isMovingPhotoVideoRequest =
1649         cmd.GetQuerySetParam(MEDIA_MOVING_PHOTO_OPRN_KEYWORD) == OPEN_MOVING_PHOTO_VIDEO;
1650     if (isMovingPhotoVideoRequest) {
1651         CHECK_AND_RETURN_RET_LOG(
1652             CheckOpenMovingPhoto(fileAsset->GetPhotoSubType(), fileAsset->GetMovingPhotoEffectMode(),
1653                 cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD)),
1654             E_INVALID_VALUES,
1655             "Non-moving photo requesting moving photo operation, file id: %{public}s, actual subtype: %{public}d",
1656             id.c_str(), fileAsset->GetPhotoSubType());
1657         movingPhotoVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(path);
1658     }
1659 
1660     string sourcePath = isMovingPhotoVideoRequest ?
1661         MediaFileUtils::GetMovingPhotoVideoPath(GetEditDataSourcePath(path)) :
1662         GetEditDataSourcePath(path);
1663     if (sourcePath.empty() || !MediaFileUtils::IsFileExists(sourcePath)) {
1664         MEDIA_INFO_LOG("sourcePath does not exist: %{private}s", sourcePath.c_str());
1665         return OpenFileWithPrivacy(isMovingPhotoVideoRequest ? movingPhotoVideoPath : path, "r", id);
1666     } else {
1667         return OpenFileWithPrivacy(sourcePath, "r", id);
1668     }
1669 }
1670 
CommitEditOpen(MediaLibraryCommand & cmd)1671 int32_t MediaLibraryPhotoOperations::CommitEditOpen(MediaLibraryCommand &cmd)
1672 {
1673     string uriString = cmd.GetUriStringWithoutSegment();
1674     string id = MediaFileUtils::GetIdFromUri(uriString);
1675     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
1676         return E_INVALID_URI;
1677     }
1678 
1679     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, id,
1680         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1681     if (fileAsset == nullptr) {
1682         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, uri:%{public}s", uriString.c_str());
1683         return E_INVALID_URI;
1684     }
1685     int32_t fileId = stoi(id);  // after MediaLibraryDataManagerUtils::IsNumber, id must be number
1686     if (!PhotoEditingRecord::GetInstance()->StartCommitEdit(fileId)) {
1687         return E_IS_IN_REVERT;
1688     }
1689     int32_t fd = CommitEditOpenExecute(fileAsset);
1690     if (fd < 0) {
1691         PhotoEditingRecord::GetInstance()->EndCommitEdit(fileId);
1692     }
1693     return fd;
1694 }
1695 
CommitEditOpenExecute(const shared_ptr<FileAsset> & fileAsset)1696 int32_t MediaLibraryPhotoOperations::CommitEditOpenExecute(const shared_ptr<FileAsset> &fileAsset)
1697 {
1698     int32_t err = CheckFileAssetStatus(fileAsset);
1699     CHECK_AND_RETURN_RET(err == E_OK, err);
1700     string path = fileAsset->GetFilePath();
1701     if (path.empty()) {
1702         MEDIA_ERR_LOG("Can not get file path");
1703         return E_INVALID_URI;
1704     }
1705     if (fileAsset->GetPhotoEditTime() == 0) {
1706         string sourceDirPath = GetEditDataDirPath(path);
1707         CHECK_AND_RETURN_RET_LOG(!sourceDirPath.empty(), E_INVALID_URI, "Can not get edit dir path");
1708         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(sourceDirPath), E_HAS_FS_ERROR,
1709             "Can not create dir %{private}s", sourceDirPath.c_str());
1710         string sourcePath = GetEditDataSourcePath(path);
1711         CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Can not get edit source path");
1712         if (!MediaFileUtils::IsFileExists(sourcePath)) {
1713             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(path, sourcePath) == E_SUCCESS, E_HAS_FS_ERROR,
1714                 "Move file failed, srcPath:%{private}s, newPath:%{private}s", path.c_str(), sourcePath.c_str());
1715             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(path), E_HAS_FS_ERROR,
1716                 "Create file failed, path:%{private}s", path.c_str());
1717         } else {
1718             MEDIA_WARN_LOG("Unexpected source file already exists for a not-edited asset, display name: %{private}s",
1719                 fileAsset->GetDisplayName().c_str());
1720         }
1721     }
1722 
1723     string fileId = MediaFileUtils::GetIdFromUri(fileAsset->GetUri());
1724     return OpenFileWithPrivacy(path, "rw", fileId);
1725 }
1726 
UpdateEditTime(int32_t fileId,int64_t time)1727 static int32_t UpdateEditTime(int32_t fileId, int64_t time)
1728 {
1729     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1730     if (rdbStore == nullptr) {
1731         return E_HAS_DB_ERROR;
1732     }
1733     MediaLibraryCommand updatePendingCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
1734     updatePendingCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
1735     ValuesBucket updateValues;
1736     updateValues.PutLong(PhotoColumn::PHOTO_EDIT_TIME, time);
1737     updatePendingCmd.SetValueBucket(updateValues);
1738     int32_t rowId = 0;
1739     int32_t result = rdbStore->Update(updatePendingCmd, rowId);
1740     if (result != NativeRdb::E_OK || rowId <= 0) {
1741         MEDIA_ERR_LOG("Update File pending failed. Result %{public}d.", result);
1742         return E_HAS_DB_ERROR;
1743     }
1744 
1745     return E_OK;
1746 }
1747 
RevertMetadata(int32_t fileId,int64_t time,int32_t effectMode,int32_t photoSubType)1748 static int32_t RevertMetadata(int32_t fileId, int64_t time, int32_t effectMode, int32_t photoSubType)
1749 {
1750     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1751     if (rdbStore == nullptr) {
1752         return E_HAS_DB_ERROR;
1753     }
1754     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
1755     cmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
1756     ValuesBucket updateValues;
1757     updateValues.PutLong(PhotoColumn::PHOTO_EDIT_TIME, time);
1758     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
1759         updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
1760             static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT));
1761         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
1762     } else if (photoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) &&
1763         effectMode != static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT)) {
1764         updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
1765             static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT));
1766     }
1767     cmd.SetValueBucket(updateValues);
1768     int32_t rowId = 0;
1769     int32_t result = rdbStore->Update(cmd, rowId);
1770     if (result != NativeRdb::E_OK || rowId <= 0) {
1771         MEDIA_ERR_LOG("Failed to revert metadata. Result %{public}d.", result);
1772         return E_HAS_DB_ERROR;
1773     }
1774     return E_OK;
1775 }
1776 
UpdateEffectMode(int32_t fileId,int32_t effectMode)1777 static int32_t UpdateEffectMode(int32_t fileId, int32_t effectMode)
1778 {
1779     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1780     if (rdbStore == nullptr) {
1781         MEDIA_ERR_LOG("Failed to get rdbStore when updating effect mode");
1782         return E_HAS_DB_ERROR;
1783     }
1784 
1785     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
1786     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
1787     ValuesBucket updateValues;
1788     updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
1789     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
1790         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
1791     } else {
1792         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
1793     }
1794     updateCmd.SetValueBucket(updateValues);
1795 
1796     int32_t updateRows = -1;
1797     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
1798     if (errCode != NativeRdb::E_OK || updateRows < 0) {
1799         MEDIA_ERR_LOG("Update effect mode failed. errCode:%{public}d, updateRows:%{public}d.", errCode, updateRows);
1800         return E_HAS_DB_ERROR;
1801     }
1802     return E_OK;
1803 }
1804 
UpdateMimeType(const int32_t & fileId,const std::string mimeType)1805 static int32_t UpdateMimeType(const int32_t &fileId, const std::string mimeType)
1806 {
1807     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1808     if (rdbStore == nullptr) {
1809         MEDIA_ERR_LOG("Failed to get rdbStore when updating mime type");
1810         return E_HAS_DB_ERROR;
1811     }
1812     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
1813     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
1814     ValuesBucket updateValues;
1815 
1816     updateCmd.SetValueBucket(updateValues);
1817     int32_t updateRows = -1;
1818     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
1819     if (errCode != NativeRdb::E_OK || updateRows < 0) {
1820         MEDIA_ERR_LOG("Update mime type failed. errCode:%{public}d, updateRows:%{public}d.", errCode, updateRows);
1821         return E_HAS_DB_ERROR;
1822     }
1823     return E_OK;
1824 }
1825 
GetModityExtensionPath(std::string & path,std::string & modifyFilePath,const std::string & extension)1826 static void GetModityExtensionPath(std::string &path, std::string &modifyFilePath, const std::string &extension)
1827 {
1828     size_t pos = path.find_last_of('.');
1829     modifyFilePath = path.substr(0, pos) + extension;
1830 }
1831 
UpdateExtension(const int32_t & fileId,std::string & mimeType,const int32_t & fileType,std::string & oldFilePath)1832 int32_t MediaLibraryPhotoOperations::UpdateExtension(const int32_t &fileId, std::string &mimeType,
1833     const int32_t &fileType, std::string &oldFilePath)
1834 {
1835     ImageFileType type = static_cast<ImageFileType>(fileType);
1836     auto itr = IMAGE_FILE_TYPE_MAP.find(type);
1837     if (itr == IMAGE_FILE_TYPE_MAP.end()) {
1838         MEDIA_ERR_LOG("fileType : %{public} is not support", fileType);
1839         return E_INVALID_ARGUMENTS;
1840     }
1841     mimeType = itr->second;
1842     auto extensionItr = IMAGE_EXTENSION_MAP.find(type);
1843     if (itr == IMAGE_EXTENSION_MAP.end()) {
1844         MEDIA_ERR_LOG("fileType : %{public} is not support", fileType);
1845         return E_INVALID_ARGUMENTS;
1846     }
1847     std::string extension = extensionItr->second;
1848     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1849     if (rdbStore == nullptr) {
1850         MEDIA_ERR_LOG("Failed to get rdbStore when updating mime type");
1851         return E_HAS_DB_ERROR;
1852     }
1853     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileId),
1854                                                          OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1855     std::string filePath = fileAsset->GetFilePath();
1856     std::string displayName = fileAsset->GetDisplayName();
1857     std::string modifyFilePath;
1858     std::string modifyDisplayName;
1859     GetModityExtensionPath(filePath, modifyFilePath, extension);
1860     GetModityExtensionPath(displayName, modifyDisplayName, extension);
1861     MEDIA_DEBUG_LOG("modifyFilePath:%{public}s", modifyFilePath.c_str());
1862     MEDIA_DEBUG_LOG("modifyDisplayName:%{public}s", modifyDisplayName.c_str());
1863     if ((modifyFilePath == filePath) && (modifyDisplayName == displayName)) {
1864         return E_OK;
1865     }
1866     UpdateEditDataPath(filePath, extension);
1867     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
1868     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
1869     ValuesBucket updateValues;
1870     updateValues.PutString(MediaColumn::MEDIA_FILE_PATH, modifyFilePath);
1871     updateValues.PutString(MediaColumn::MEDIA_NAME, modifyDisplayName);
1872     updateValues.PutString(MediaColumn::MEDIA_MIME_TYPE, mimeType);
1873     updateCmd.SetValueBucket(updateValues);
1874     int32_t updateRows = -1;
1875     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
1876     if (errCode != NativeRdb::E_OK || updateRows < 0) {
1877         MEDIA_ERR_LOG("Update extension failed. errCode:%{public}d, updateRows:%{public}d.", errCode, updateRows);
1878         return E_HAS_DB_ERROR;
1879     }
1880     oldFilePath = filePath;
1881     return E_OK;
1882 }
1883 
UpdateEditDataPath(std::string filePath,const std::string & extension)1884 void MediaLibraryPhotoOperations::UpdateEditDataPath(std::string filePath, const std::string &extension)
1885 {
1886     string editDataPath = GetEditDataDirPath(filePath);
1887     string tempOutputPath = editDataPath;
1888     size_t pos = tempOutputPath.find_last_of('.');
1889     if (pos != string::npos) {
1890         tempOutputPath.replace(pos, extension.length(), extension);
1891         rename(editDataPath.c_str(), tempOutputPath.c_str());
1892         MEDIA_DEBUG_LOG("rename, src: %{public}s, dest: %{public}s",
1893             editDataPath.c_str(), tempOutputPath.c_str());
1894     }
1895 }
1896 
DeleteAbnormalFile(std::string & assetPath,const int32_t & fileId,const std::string & oldFilePath)1897 void MediaLibraryPhotoOperations::DeleteAbnormalFile(std::string &assetPath, const int32_t &fileId,
1898     const std::string &oldFilePath)
1899 {
1900     MEDIA_INFO_LOG("DeleteAbnormalFile fileId:%{public}d, assetPath = %{public}s", fileId, assetPath.c_str());
1901     MediaLibraryObjectUtils::ScanFileAsync(assetPath, to_string(fileId), MediaLibraryApi::API_10);
1902     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1903     vector<string> columns = { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH};
1904     string whereClause = MediaColumn::MEDIA_FILE_PATH + "= ?";
1905     vector<string> args = {oldFilePath};
1906     predicates.SetWhereClause(whereClause);
1907     predicates.SetWhereArgs(args);
1908     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
1909     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1910         MediaFileUtils::DeleteFile(oldFilePath);
1911         DeleteRevertMessage(oldFilePath);
1912         return;
1913     }
1914     int32_t fileIdTemp = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
1915     string filePathTemp = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
1916     resultSet->Close();
1917     MEDIA_INFO_LOG("DeleteAbnormalFile fileId:%{public}d, filePathTemp = %{public}s", fileIdTemp, filePathTemp.c_str());
1918     auto oldFileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileIdTemp),
1919                                            OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1920     if (oldFileAsset != nullptr) {
1921         int32_t deleteRow = DeletePhoto(oldFileAsset, MediaLibraryApi::API_10);
1922         if (deleteRow < 0) {
1923             MEDIA_ERR_LOG("delete photo failed, deleteRow=%{public}d", deleteRow);
1924         }
1925     }
1926 }
1927 
CommitEditInsert(MediaLibraryCommand & cmd)1928 int32_t MediaLibraryPhotoOperations::CommitEditInsert(MediaLibraryCommand &cmd)
1929 {
1930     const ValuesBucket &values = cmd.GetValueBucket();
1931     string editData;
1932     int32_t id = 0;
1933     if (!GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id)) {
1934         MEDIA_ERR_LOG("Failed to get fileId");
1935         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
1936         return E_INVALID_VALUES;
1937     }
1938     if (!GetStringFromValuesBucket(values, EDIT_DATA, editData)) {
1939         MEDIA_ERR_LOG("Failed to get editdata");
1940         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
1941         return E_INVALID_VALUES;
1942     }
1943 
1944     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(id),
1945         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1946     if (fileAsset == nullptr) {
1947         MEDIA_ERR_LOG("Get FileAsset Failed, fileId=%{public}d", id);
1948         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
1949         return E_INVALID_VALUES;
1950     }
1951     fileAsset->SetId(id);
1952     int32_t ret = CommitEditInsertExecute(fileAsset, editData);
1953     PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
1954     MEDIA_INFO_LOG("commit edit finished, fileId=%{public}d", id);
1955     return ret;
1956 }
1957 
NotifyFormMap(const int32_t fileId,const string & path,const bool isSave)1958 static void NotifyFormMap(const int32_t fileId, const string& path, const bool isSave)
1959 {
1960     string uri = MediaLibraryFormMapOperations::GetUriByFileId(fileId, path);
1961     if (uri.empty()) {
1962         MEDIA_WARN_LOG("Failed to GetUriByFileId(%{public}d, %{private}s)", fileId, path.c_str());
1963         return;
1964     }
1965 
1966     vector<int64_t> formIds;
1967     MediaLibraryFormMapOperations::GetFormMapFormId(uri.c_str(), formIds);
1968     if (!formIds.empty()) {
1969         MediaLibraryFormMapOperations::PublishedChange(uri, formIds, isSave);
1970     }
1971 }
1972 
CommitEditInsertExecute(const shared_ptr<FileAsset> & fileAsset,const string & editData)1973 int32_t MediaLibraryPhotoOperations::CommitEditInsertExecute(const shared_ptr<FileAsset> &fileAsset,
1974     const string &editData)
1975 {
1976     int32_t errCode = CheckFileAssetStatus(fileAsset);
1977     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
1978 
1979     string path = fileAsset->GetPath();
1980     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_VALUES, "File path is empty");
1981     string editDataPath = GetEditDataPath(path);
1982     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_VALUES, "EditData path is empty");
1983     if (!MediaFileUtils::IsFileExists(editDataPath)) {
1984         string dataPathDir = GetEditDataDirPath(path);
1985         CHECK_AND_RETURN_RET_LOG(!dataPathDir.empty(), E_INVALID_PATH,
1986             "Get edit data dir path from path %{private}s failed", path.c_str());
1987         if (!MediaFileUtils::IsDirectory(dataPathDir)) {
1988             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dataPathDir), E_HAS_FS_ERROR,
1989                 "Failed to create dir %{private}s", dataPathDir.c_str());
1990         }
1991         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateAsset(editDataPath) == E_SUCCESS, E_HAS_FS_ERROR,
1992             "Failed to create file %{private}s", editDataPath.c_str());
1993     }
1994     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataPath, editData), E_HAS_FS_ERROR,
1995         "Failed to write editdata path:%{private}s", editDataPath.c_str());
1996 
1997     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
1998         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), {
1999         to_string(PhotoAlbumSubType::IMAGE),
2000         to_string(PhotoAlbumSubType::VIDEO),
2001         to_string(PhotoAlbumSubType::SCREENSHOT),
2002         to_string(PhotoAlbumSubType::FAVORITE),
2003         to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
2004     });
2005     errCode = UpdateEditTime(fileAsset->GetId(), MediaFileUtils::UTCTimeSeconds());
2006     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to update edit time, fileId:%{public}d",
2007         fileAsset->GetId());
2008     ScanFile(path, false, true, true);
2009     NotifyFormMap(fileAsset->GetId(), fileAsset->GetFilePath(), false);
2010     return E_OK;
2011 }
2012 
RevertToOrigin(MediaLibraryCommand & cmd)2013 int32_t MediaLibraryPhotoOperations::RevertToOrigin(MediaLibraryCommand &cmd)
2014 {
2015     const ValuesBucket &values = cmd.GetValueBucket();
2016     int32_t fileId = 0;
2017     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, fileId), E_INVALID_VALUES,
2018         "Failed to get fileId");
2019 
2020     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileId),
2021         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2022     if (fileAsset == nullptr) {
2023         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, fileId:%{public}d", fileId);
2024         return E_INVALID_VALUES;
2025     }
2026     fileAsset->SetId(fileId);
2027     if (!PhotoEditingRecord::GetInstance()->StartRevert(fileId)) {
2028         return E_IS_IN_COMMIT;
2029     }
2030 
2031     int32_t errCode = DoRevertEdit(fileAsset);
2032     PhotoEditingRecord::GetInstance()->EndRevert(fileId);
2033     return errCode;
2034 }
2035 
ResetOcrInfo(const int32_t & fileId)2036 void ResetOcrInfo(const int32_t &fileId)
2037 {
2038     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2039     if (rdbStore == nullptr) {
2040         MEDIA_ERR_LOG("MediaLibrary rdbStore is nullptr!");
2041         return;
2042     }
2043     string sqlDeleteOcr = "DELETE FROM " + VISION_OCR_TABLE + " WHERE file_id = " + to_string(fileId) + ";" +
2044         " UPDATE " + VISION_TOTAL_TABLE + " SET ocr = 0 WHERE file_id = " + to_string(fileId) + ";";
2045 
2046     int ret = rdbStore->ExecuteSql(sqlDeleteOcr);
2047     if (ret != NativeRdb::E_OK) {
2048         MEDIA_ERR_LOG("Update ocr info failed, ret = %{public}d, file id is %{public}d", ret, fileId);
2049     }
2050 }
2051 
UpdateMovingPhotoSubtype(int32_t fileId,int32_t currentPhotoSubType)2052 int32_t MediaLibraryPhotoOperations::UpdateMovingPhotoSubtype(int32_t fileId, int32_t currentPhotoSubType)
2053 {
2054     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2055     if (rdbStore == nullptr) {
2056         MEDIA_ERR_LOG("Failed to get rdbStore when updating subtype");
2057         return E_HAS_DB_ERROR;
2058     }
2059 
2060     int32_t updatePhotoSubType = currentPhotoSubType == static_cast<int32_t>(PhotoSubType::DEFAULT) ?
2061         static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) : static_cast<int32_t>(PhotoSubType::DEFAULT);
2062     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2063     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2064     ValuesBucket updateValues;
2065     updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, updatePhotoSubType);
2066     if (currentPhotoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2067         updateValues.PutInt(PhotoColumn::PHOTO_ORIGINAL_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2068     }
2069     updateCmd.SetValueBucket(updateValues);
2070     int32_t updateRows = -1;
2071     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
2072     if (errCode != NativeRdb::E_OK || updateRows < 0) {
2073         MEDIA_ERR_LOG("Update subtype field failed. errCode:%{public}d, updateRows:%{public}d", errCode, updateRows);
2074         return E_HAS_DB_ERROR;
2075     }
2076     return E_OK;
2077 }
2078 
DoRevertEdit(const std::shared_ptr<FileAsset> & fileAsset)2079 int32_t MediaLibraryPhotoOperations::DoRevertEdit(const std::shared_ptr<FileAsset> &fileAsset)
2080 {
2081     int32_t errCode = CheckFileAssetStatus(fileAsset);
2082     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
2083     int32_t fileId = fileAsset->GetId();
2084     if (fileAsset->GetPhotoEditTime() == 0) {
2085         MEDIA_INFO_LOG("File %{public}d is not edit", fileId);
2086         return E_OK;
2087     }
2088 
2089     string path = fileAsset->GetFilePath();
2090     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI, "Can not get file path, fileId=%{public}d", fileId);
2091     string sourcePath = GetEditDataSourcePath(path);
2092     CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Cannot get source path, id=%{public}d", fileId);
2093     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(sourcePath), E_NO_SUCH_FILE, "Can not get source file");
2094 
2095     int32_t subtype = static_cast<int32_t>(fileAsset->GetPhotoSubType());
2096     int32_t movingPhotoSubtype = static_cast<int32_t>(PhotoSubType::MOVING_PHOTO);
2097     if (subtype == movingPhotoSubtype || fileAsset->GetOriginalSubType() == movingPhotoSubtype) {
2098         string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourcePath);
2099         errCode = RevertMovingPhotoVideo(fileAsset, path, sourceVideoPath, subtype);
2100         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_FS_ERROR, "Failed to revert movingPhoto video");
2101     }
2102 
2103     string editDataPath = GetEditDataPath(path);
2104     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_URI, "Cannot get editdata path, id=%{public}d", fileId);
2105 
2106     errCode = RevertMetadata(fileId, 0, fileAsset->GetMovingPhotoEffectMode(), fileAsset->GetPhotoSubType());
2107     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_DB_ERROR, "Failed to update data, fileId=%{public}d", fileId);
2108     ResetOcrInfo(fileId);
2109     if (MediaFileUtils::IsFileExists(editDataPath)) {
2110         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteFile(editDataPath), E_HAS_FS_ERROR,
2111             "Failed to delete edit data, path:%{private}s", editDataPath.c_str());
2112     }
2113 
2114     if (MediaFileUtils::IsFileExists(path)) {
2115         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteFile(path), E_HAS_FS_ERROR,
2116             "Failed to delete asset, path:%{private}s", path.c_str());
2117     }
2118 
2119     string editDataCameraPath = GetEditDataCameraPath(path);
2120     if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
2121         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(sourcePath, path) == E_OK, E_HAS_FS_ERROR,
2122             "Can not modify %{private}s to %{private}s", sourcePath.c_str(), path.c_str());
2123     } else {
2124         string editData;
2125         CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
2126             "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
2127         CHECK_AND_RETURN_RET_LOG(AddFiltersToPhoto(sourcePath, path, editData) == E_OK, E_FAIL,
2128             "Failed to add filters to photo");
2129     }
2130 
2131     ScanFile(path, true, true, true);
2132     // revert cloud enhancement ce_available
2133     EnhancementManager::GetInstance().RevertEditUpdateInternal(fileId);
2134     NotifyFormMap(fileAsset->GetId(), fileAsset->GetFilePath(), false);
2135     return E_OK;
2136 }
2137 
DeleteRevertMessage(const string & path)2138 void MediaLibraryPhotoOperations::DeleteRevertMessage(const string &path)
2139 {
2140     if (path.empty()) {
2141         MEDIA_ERR_LOG("Input path is empty");
2142         return;
2143     }
2144 
2145     string editDirPath = GetEditDataDirPath(path);
2146     if (editDirPath.empty()) {
2147         MEDIA_ERR_LOG("Can not get edit data dir path from path %{private}s", path.c_str());
2148         return;
2149     }
2150 
2151     if (!MediaFileUtils::IsDirectory(editDirPath)) {
2152         return;
2153     }
2154     if (!MediaFileUtils::DeleteDir(editDirPath)) {
2155         MEDIA_ERR_LOG("Failed to delete %{private}s dir, filePath is %{private}s",
2156             editDirPath.c_str(), path.c_str());
2157         return;
2158     }
2159     return;
2160 }
2161 
Move(const string & srcPath,const string & destPath)2162 static int32_t Move(const string& srcPath, const string& destPath)
2163 {
2164     if (!MediaFileUtils::IsFileExists(srcPath)) {
2165         MEDIA_ERR_LOG("srcPath: %{private}s does not exist!", srcPath.c_str());
2166         return E_NO_SUCH_FILE;
2167     }
2168 
2169     if (destPath.empty()) {
2170         MEDIA_ERR_LOG("Failed to check empty destPath");
2171         return E_INVALID_VALUES;
2172     }
2173 
2174     int32_t ret = rename(srcPath.c_str(), destPath.c_str());
2175     if (ret < 0) {
2176         MEDIA_ERR_LOG("Failed to rename, src: %{public}s, dest: %{public}s, ret: %{public}d, errno: %{public}d",
2177             srcPath.c_str(), destPath.c_str(), ret, errno);
2178     }
2179     return ret;
2180 }
2181 
RevertMovingPhotoVideo(const std::shared_ptr<FileAsset> & fileAsset,const string & path,const string & sourceVideoPath,int32_t subtype)2182 int32_t MediaLibraryPhotoOperations::RevertMovingPhotoVideo(const std::shared_ptr<FileAsset> &fileAsset,
2183     const string &path, const string &sourceVideoPath, int32_t subtype)
2184 {
2185     int32_t fileId = fileAsset->GetId();
2186     CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_URI,
2187         "Cannot get source video path, id=%{public}d", fileId);
2188     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(sourceVideoPath), E_NO_SUCH_FILE,
2189         "Can not get source video file, id=%{public}d", fileId);
2190 
2191     int32_t errCode = E_OK;
2192     if (subtype != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2193         errCode = UpdateMovingPhotoSubtype(fileAsset->GetId(), subtype);
2194         CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
2195     }
2196     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(path);
2197     CHECK_AND_RETURN_RET_LOG(Move(sourceVideoPath, videoPath) == E_OK, E_HAS_FS_ERROR, "Failed to move video");
2198     return errCode;
2199 }
2200 
IsNeedRevertEffectMode(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,int32_t & effectMode)2201 bool MediaLibraryPhotoOperations::IsNeedRevertEffectMode(MediaLibraryCommand& cmd,
2202     const shared_ptr<FileAsset>& fileAsset, int32_t& effectMode)
2203 {
2204     if (fileAsset->GetPhotoSubType() != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) &&
2205         fileAsset->GetMovingPhotoEffectMode() != static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2206         return false;
2207     }
2208 
2209     if (!GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode) ||
2210         (effectMode != static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT) &&
2211         effectMode != static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY))) {
2212         return false;
2213     }
2214 
2215     if (fileAsset->GetPhotoEditTime() != 0) {
2216         ProcessEditedEffectMode(cmd, effectMode);
2217         return false;
2218     }
2219     return true;
2220 }
2221 
ProcessEditedEffectMode(MediaLibraryCommand & cmd,int32_t effectMode)2222 void MediaLibraryPhotoOperations::ProcessEditedEffectMode(MediaLibraryCommand& cmd, int32_t effectMode)
2223 {
2224     ValuesBucket& updateValues = cmd.GetValueBucket();
2225     updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2226     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2227         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
2228     } else {
2229         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2230     }
2231 }
2232 
RevertToOriginalEffectMode(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNeedScan)2233 int32_t MediaLibraryPhotoOperations::RevertToOriginalEffectMode(
2234     MediaLibraryCommand& cmd, const shared_ptr<FileAsset>& fileAsset, bool& isNeedScan)
2235 {
2236     isNeedScan = false;
2237     int32_t effectMode{0};
2238     if (!IsNeedRevertEffectMode(cmd, fileAsset, effectMode)) {
2239         return E_OK;
2240     }
2241     isNeedScan = true;
2242     ValuesBucket& updateValues = cmd.GetValueBucket();
2243     updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2244     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2245         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
2246     } else {
2247         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2248     }
2249 
2250     string imagePath = fileAsset->GetFilePath();
2251     string sourceImagePath = GetEditDataSourcePath(imagePath);
2252     CHECK_AND_RETURN_RET_LOG(!sourceImagePath.empty(), E_INVALID_PATH, "Cannot get source image path");
2253     string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
2254     CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_PATH, "Cannot get source video path");
2255 
2256     bool isSourceImageExist = MediaFileUtils::IsFileExists(sourceImagePath);
2257     bool isSourceVideoExist = MediaFileUtils::IsFileExists(sourceVideoPath);
2258     if (!isSourceImageExist || !isSourceVideoExist) {
2259         MEDIA_INFO_LOG("isSourceImageExist=%{public}d, isSourceVideoExist=%{public}d",
2260             isSourceImageExist, isSourceVideoExist);
2261         isNeedScan = false;
2262         return E_OK;
2263     }
2264     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(imagePath);
2265     int32_t errCode = Move(sourceVideoPath, videoPath);
2266     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_FS_ERROR, "Failed to move video from %{private}s to %{private}s",
2267         sourceVideoPath.c_str(), videoPath.c_str());
2268     string editDataCameraPath = GetEditDataCameraPath(imagePath);
2269     if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
2270         errCode = Move(sourceImagePath, imagePath);
2271         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_FS_ERROR,
2272             "Failed to move image from %{private}s to %{private}s",
2273             sourceImagePath.c_str(), imagePath.c_str());
2274     } else {
2275         string editData;
2276         CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
2277             "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
2278         CHECK_AND_RETURN_RET_LOG(AddFiltersToPhoto(sourceImagePath, imagePath, editData) == E_OK,
2279             E_FAIL, "Failed to add filters to photo");
2280     }
2281     return E_OK;
2282 }
2283 
MoveCacheFile(MediaLibraryCommand & cmd,int32_t subtype,const string & cachePath,const string & destPath)2284 int32_t MediaLibraryPhotoOperations::MoveCacheFile(
2285     MediaLibraryCommand& cmd, int32_t subtype, const string& cachePath, const string& destPath)
2286 {
2287     if (subtype != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2288         return Move(cachePath, destPath);
2289     }
2290 
2291     // write moving photo
2292     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoImage(cachePath), E_INVALID_MOVING_PHOTO,
2293         "Failed to check image of moving photo");
2294     string cacheMovingPhotoVideoName;
2295     if (GetStringFromValuesBucket(cmd.GetValueBucket(), CACHE_MOVING_PHOTO_VIDEO_NAME, cacheMovingPhotoVideoName) &&
2296             !cacheMovingPhotoVideoName.empty()) {
2297         string cacheVideoPath = GetAssetCacheDir() + "/" + cacheMovingPhotoVideoName;
2298         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoVideo(cacheVideoPath), E_INVALID_MOVING_PHOTO,
2299             "Failed to check video of moving photo");
2300         string destVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(destPath);
2301         int32_t errCode = Move(cacheVideoPath, destVideoPath);
2302         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
2303             "Failed to move moving photo video from %{private}s to %{private}s, errCode: %{public}d",
2304             cacheVideoPath.c_str(), destVideoPath.c_str(), errCode);
2305     }
2306     return Move(cachePath, destPath);
2307 }
2308 
CheckCacheCmd(MediaLibraryCommand & cmd,int32_t subtype,const string & displayName)2309 bool MediaLibraryPhotoOperations::CheckCacheCmd(MediaLibraryCommand& cmd, int32_t subtype, const string& displayName)
2310 {
2311     string cacheFileName;
2312     if (!GetStringFromValuesBucket(cmd.GetValueBucket(), CACHE_FILE_NAME, cacheFileName)) {
2313         MEDIA_ERR_LOG("Failed to get cache file name");
2314         return false;
2315     }
2316 
2317     string cacheMimeType = MimeTypeUtils::GetMimeTypeFromExtension(MediaFileUtils::GetExtensionFromPath(cacheFileName));
2318     string assetMimeType = MimeTypeUtils::GetMimeTypeFromExtension(MediaFileUtils::GetExtensionFromPath(displayName));
2319     if (cacheMimeType.compare(assetMimeType) != 0) {
2320         MEDIA_ERR_LOG("cache mime type %{public}s mismatches the asset %{public}s",
2321             cacheMimeType.c_str(), assetMimeType.c_str());
2322         return false;
2323     }
2324 
2325     int32_t id = 0;
2326     bool isCreation = !GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MEDIA_ID, id);
2327     if (subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) && isCreation) {
2328         string movingPhotoVideoName;
2329         bool containsVideo = GetStringFromValuesBucket(cmd.GetValueBucket(),
2330             CACHE_MOVING_PHOTO_VIDEO_NAME, movingPhotoVideoName);
2331         if (!containsVideo) {
2332             MEDIA_ERR_LOG("Failed to get video when creating moving photo");
2333             return false;
2334         }
2335 
2336         string videoExtension = MediaFileUtils::GetExtensionFromPath(movingPhotoVideoName);
2337         if (!MediaFileUtils::CheckMovingPhotoVideoExtension(videoExtension)) {
2338             MEDIA_ERR_LOG("Failed to check video of moving photo, extension: %{public}s", videoExtension.c_str());
2339             return false;
2340         }
2341     }
2342     return true;
2343 }
2344 
ParseMediaAssetEditData(MediaLibraryCommand & cmd,string & editData)2345 int32_t MediaLibraryPhotoOperations::ParseMediaAssetEditData(MediaLibraryCommand& cmd, string& editData)
2346 {
2347     string compatibleFormat;
2348     string formatVersion;
2349     string data;
2350     const ValuesBucket& values = cmd.GetValueBucket();
2351     bool containsCompatibleFormat = GetStringFromValuesBucket(values, COMPATIBLE_FORMAT, compatibleFormat);
2352     bool containsFormatVersion = GetStringFromValuesBucket(values, FORMAT_VERSION, formatVersion);
2353     bool containsData = GetStringFromValuesBucket(values, EDIT_DATA, data);
2354     bool notContainsEditData = !containsCompatibleFormat && !containsFormatVersion && !containsData;
2355     bool containsEditData = containsCompatibleFormat && containsFormatVersion && containsData;
2356     if (!containsEditData && !notContainsEditData) {
2357         MEDIA_ERR_LOG(
2358             "Failed to parse edit data, compatibleFormat: %{public}s, formatVersion: %{public}s, data: %{public}s",
2359             compatibleFormat.c_str(), formatVersion.c_str(), data.c_str());
2360         return E_INVALID_VALUES;
2361     }
2362 
2363     nlohmann::json editDataJson;
2364     string bundleName = cmd.GetBundleName();
2365     editDataJson[COMPATIBLE_FORMAT] = compatibleFormat.empty() ? bundleName : compatibleFormat;
2366     editDataJson[FORMAT_VERSION] = formatVersion;
2367     editDataJson[EDIT_DATA] = data;
2368     editDataJson[APP_ID] = bundleName;
2369     editData = editDataJson.dump();
2370     return E_OK;
2371 }
2372 
ParseCloudEnhancementEditData(string & editData)2373 void MediaLibraryPhotoOperations::ParseCloudEnhancementEditData(string& editData)
2374 {
2375     if (!nlohmann::json::accept(editData)) {
2376         MEDIA_WARN_LOG("Failed to verify the editData format, editData is: %{private}s",
2377             editData.c_str());
2378         return;
2379     }
2380     string editDataJsonStr;
2381     nlohmann::json jsonObject = nlohmann::json::parse(editData);
2382     if (jsonObject.contains(EDIT_DATA)) {
2383         editDataJsonStr = jsonObject[EDIT_DATA];
2384         nlohmann::json editDataJson = nlohmann::json::parse(editDataJsonStr, nullptr, false);
2385         if (editDataJson.is_discarded()) {
2386             MEDIA_INFO_LOG("editDataJson parse failed");
2387             return;
2388         }
2389         string editDataStr = editDataJson.dump();
2390         editData = editDataStr;
2391     }
2392 }
2393 
IsSetEffectMode(MediaLibraryCommand & cmd)2394 bool MediaLibraryPhotoOperations::IsSetEffectMode(MediaLibraryCommand &cmd)
2395 {
2396     int32_t effectMode;
2397     return GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2398 }
2399 
IsContainsData(MediaLibraryCommand & cmd)2400 bool MediaLibraryPhotoOperations::IsContainsData(MediaLibraryCommand &cmd)
2401 {
2402     string compatibleFormat;
2403     string formatVersion;
2404     string data;
2405     const ValuesBucket& values = cmd.GetValueBucket();
2406     bool containsCompatibleFormat = GetStringFromValuesBucket(values, COMPATIBLE_FORMAT, compatibleFormat);
2407     bool containsFormatVersion = GetStringFromValuesBucket(values, FORMAT_VERSION, formatVersion);
2408     bool containsData = GetStringFromValuesBucket(values, EDIT_DATA, data);
2409     return containsCompatibleFormat && containsFormatVersion && containsData;
2410 }
2411 
IsCameraEditData(MediaLibraryCommand & cmd)2412 bool MediaLibraryPhotoOperations::IsCameraEditData(MediaLibraryCommand &cmd)
2413 {
2414     string bundleName = cmd.GetBundleName();
2415     return IsContainsData(cmd) && (count(CAMERA_BUNDLE_NAMES.begin(), CAMERA_BUNDLE_NAMES.end(), bundleName) > 0);
2416 }
2417 
ReadEditdataFromFile(const std::string & editDataPath,std::string & editData)2418 int32_t MediaLibraryPhotoOperations::ReadEditdataFromFile(const std::string &editDataPath, std::string &editData)
2419 {
2420     string editDataStr;
2421     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ReadStrFromFile(editDataPath, editDataStr), E_HAS_FS_ERROR,
2422         "Can not read editdata from %{private}s", editDataPath.c_str());
2423     if (!nlohmann::json::accept(editDataStr)) {
2424         MEDIA_WARN_LOG("Failed to verify the editData format, editData is: %{private}s", editDataStr.c_str());
2425         editData = editDataStr;
2426         return E_OK;
2427     }
2428     nlohmann::json editdataJson = nlohmann::json::parse(editDataStr);
2429     if (editdataJson.contains(EDIT_DATA)) {
2430         editData = editdataJson[EDIT_DATA];
2431     } else {
2432         editData = editDataStr;
2433     }
2434     return E_OK;
2435 }
2436 
SaveEditDataCamera(MediaLibraryCommand & cmd,const std::string & assetPath,std::string & editData)2437 int32_t MediaLibraryPhotoOperations::SaveEditDataCamera(MediaLibraryCommand &cmd, const std::string &assetPath,
2438     std::string &editData)
2439 {
2440     string editDataStr;
2441     string editDataCameraPath = GetEditDataCameraPath(assetPath);
2442     CHECK_AND_RETURN_RET_LOG(!editDataCameraPath.empty(), E_INVALID_VALUES, "Failed to get edit data path");
2443     if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
2444         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(editDataCameraPath), E_HAS_FS_ERROR,
2445             "Failed to create file %{private}s", editDataCameraPath.c_str());
2446     }
2447     int ret = ParseMediaAssetEditData(cmd, editDataStr);
2448     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataCameraPath, editDataStr), E_HAS_FS_ERROR,
2449         "Failed to write editdata:%{private}s", editDataCameraPath.c_str());
2450     const ValuesBucket& values = cmd.GetValueBucket();
2451     GetStringFromValuesBucket(values, EDIT_DATA, editData);
2452     return ret;
2453 }
2454 
SaveSourceAndEditData(const shared_ptr<FileAsset> & fileAsset,const string & editData)2455 int32_t MediaLibraryPhotoOperations::SaveSourceAndEditData(
2456     const shared_ptr<FileAsset>& fileAsset, const string& editData)
2457 {
2458     CHECK_AND_RETURN_RET_LOG(!editData.empty(), E_INVALID_VALUES, "editData is empty");
2459     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
2460     string assetPath = fileAsset->GetFilePath();
2461     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2462     string editDataPath = GetEditDataPath(assetPath);
2463     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_VALUES, "Failed to get edit data path");
2464 
2465     if (fileAsset->GetPhotoEditTime() == 0) { // the asset has not been edited before
2466         string editDataDirPath = GetEditDataDirPath(assetPath);
2467         CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Failed to get edit dir path");
2468         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
2469             "Failed to create dir %{private}s", editDataDirPath.c_str());
2470 
2471         string sourcePath = GetEditDataSourcePath(assetPath);
2472         CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Failed to get source path");
2473         if (!MediaFileUtils::IsFileExists(sourcePath)) {
2474             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetPath, sourcePath) == E_SUCCESS, E_HAS_FS_ERROR,
2475                 "Move file failed, srcPath:%{private}s, newPath:%{private}s", assetPath.c_str(), sourcePath.c_str());
2476         }
2477 
2478         if (!MediaFileUtils::IsFileExists(editDataPath)) {
2479             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(editDataPath), E_HAS_FS_ERROR,
2480                 "Failed to create file %{private}s", editDataPath.c_str());
2481         }
2482     }
2483 
2484     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataPath, editData), E_HAS_FS_ERROR,
2485         "Failed to write editdata:%{private}s", editDataPath.c_str());
2486 
2487     return E_OK;
2488 }
2489 
GetFileAsset(MediaLibraryCommand & cmd)2490 std::shared_ptr<FileAsset> MediaLibraryPhotoOperations::GetFileAsset(MediaLibraryCommand& cmd)
2491 {
2492     const ValuesBucket& values = cmd.GetValueBucket();
2493     int32_t id = 0;
2494     GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id);
2495     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME,
2496         PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::MEDIA_TIME_PENDING, PhotoColumn::MEDIA_DATE_TRASHED };
2497     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(
2498         PhotoColumn::MEDIA_ID, to_string(id), OperationObject::FILESYSTEM_PHOTO, columns);
2499     return fileAsset;
2500 }
2501 
GetPicture(const int32_t & fileId,std::shared_ptr<Media::Picture> & picture,bool isCleanImmediately,std::string & photoId,bool & isHighQualityPicture)2502 int32_t MediaLibraryPhotoOperations::GetPicture(const int32_t &fileId, std::shared_ptr<Media::Picture> &picture,
2503     bool isCleanImmediately, std::string &photoId, bool &isHighQualityPicture)
2504 {
2505     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2506     predicates.EqualTo(MediaColumn::MEDIA_ID, std::to_string(fileId));
2507     vector<string> columns = { PhotoColumn::PHOTO_ID };
2508     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2509     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2510         MEDIA_ERR_LOG("result set is empty");
2511         return E_FILE_EXIST;
2512     }
2513 
2514     photoId = GetStringVal(PhotoColumn::PHOTO_ID, resultSet);
2515     resultSet->Close();
2516     if (photoId.empty()) {
2517         MEDIA_ERR_LOG("photoId is emply fileId is: %{public}d", fileId);
2518         return E_FILE_EXIST;
2519     }
2520 
2521     MEDIA_INFO_LOG("photoId: %{public}s", photoId.c_str());
2522     auto pictureManagerThread = PictureManagerThread::GetInstance();
2523     if (pictureManagerThread != nullptr) {
2524         picture = pictureManagerThread->GetDataWithImageId(photoId, isHighQualityPicture, isCleanImmediately);
2525     }
2526     if (picture == nullptr) {
2527         MEDIA_ERR_LOG("picture is not exists!");
2528         return E_FILE_EXIST;
2529     }
2530     return E_OK;
2531 }
2532 
FinishRequestPicture(MediaLibraryCommand & cmd)2533 int32_t MediaLibraryPhotoOperations::FinishRequestPicture(MediaLibraryCommand &cmd)
2534 {
2535     const ValuesBucket& values = cmd.GetValueBucket();
2536     int32_t fileId = 0;
2537     GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, fileId);
2538 
2539     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2540     predicates.EqualTo(MediaColumn::MEDIA_ID, std::to_string(fileId));
2541     vector<string> columns = { PhotoColumn::PHOTO_ID };
2542     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2543     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2544         MEDIA_ERR_LOG("result set is empty");
2545         return E_FILE_EXIST;
2546     }
2547 
2548     string photoId = GetStringVal(PhotoColumn::PHOTO_ID, resultSet);
2549     resultSet->Close();
2550     if (photoId.empty()) {
2551         MEDIA_ERR_LOG("photoId is emply fileId is: %{public}d", fileId);
2552         return E_FILE_EXIST;
2553     }
2554 
2555     MEDIA_INFO_LOG("photoId: %{public}s", photoId.c_str());
2556     auto pictureManagerThread = PictureManagerThread::GetInstance();
2557     if (pictureManagerThread != nullptr) {
2558         pictureManagerThread->FinishAccessingPicture(photoId);
2559     }
2560     return E_OK;
2561 }
2562 
CloneSingleAsset(MediaLibraryCommand & cmd)2563 int64_t MediaLibraryPhotoOperations::CloneSingleAsset(MediaLibraryCommand &cmd)
2564 {
2565     const ValuesBucket& values = cmd.GetValueBucket();
2566     int fileId = -1;
2567     ValueObject valueObject;
2568     if (values.GetObject(MediaColumn::MEDIA_ID, valueObject)) {
2569         valueObject.GetInt(fileId);
2570     } else {
2571         MEDIA_ERR_LOG("Failed to get media id from values bucket.");
2572         return fileId;
2573     }
2574     string title;
2575     GetStringFromValuesBucket(values, MediaColumn::MEDIA_NAME, title);
2576     return MediaLibraryAlbumFusionUtils::CloneSingleAsset(static_cast<int64_t>(fileId), title);
2577 }
2578 
AddFilters(MediaLibraryCommand & cmd)2579 int32_t MediaLibraryPhotoOperations::AddFilters(MediaLibraryCommand& cmd)
2580 {
2581     if (IsCameraEditData(cmd)) {
2582         shared_ptr<FileAsset> fileAsset = GetFileAsset(cmd);
2583         return AddFiltersExecute(cmd, fileAsset, "");
2584     }
2585     return E_OK;
2586 }
2587 
ForceSavePicture(MediaLibraryCommand & cmd)2588 int32_t MediaLibraryPhotoOperations::ForceSavePicture(MediaLibraryCommand& cmd)
2589 {
2590     MEDIA_DEBUG_LOG("ForceSavePicture");
2591     int fileType = std::atoi(cmd.GetQuerySetParam(IMAGE_FILE_TYPE).c_str());
2592     int fileId = std::atoi(cmd.GetQuerySetParam(PhotoColumn::MEDIA_ID).c_str());
2593     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2594     predicates.EqualTo(MediaColumn::MEDIA_ID, std::to_string(fileId));
2595     vector<string> columns = { PhotoColumn::PHOTO_IS_TEMP };
2596     auto resultSet = MediaLibraryRdbStore::Query(predicates, columns);
2597     if (resultSet ==nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2598         MEDIA_ERR_LOG("result set is empty");
2599         return E_ERR;
2600     }
2601     if (GetInt32Val(PhotoColumn::PHOTO_IS_TEMP, resultSet) == 0) {
2602         return E_OK;
2603     }
2604     string uri = cmd.GetQuerySetParam("uri");
2605     SavePicture(fileType, fileId);
2606     string path = MediaFileUri::GetPathFromUri(uri, true);
2607     MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(path, false, false, true, fileId);
2608     return E_OK;
2609 }
2610 
SavePicture(const int32_t & fileType,const int32_t & fileId)2611 int32_t MediaLibraryPhotoOperations::SavePicture(const int32_t &fileType, const int32_t &fileId)
2612 {
2613     MEDIA_DEBUG_LOG("savePicture fileType is: %{public}d, fileId is: %{public}d", fileType, fileId);
2614     std::shared_ptr<Media::Picture> picture;
2615     std::string photoId;
2616     bool isHighQualityPicture = false;
2617     if (GetPicture(fileId, picture, false, photoId, isHighQualityPicture) != E_OK) {
2618         MEDIA_ERR_LOG("Failed to get picture");
2619         return E_FILE_EXIST;
2620     }
2621 
2622     std::string format = MIME_TYPE_JPEG;
2623     std::string oldFilePath = "";
2624     int32_t updateResult = UpdateExtension(fileId, format, fileType, oldFilePath);
2625     auto fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileId),
2626                                         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2627     string assetPath = fileAsset->GetFilePath();
2628     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2629 
2630     FileUtils::DealPicture(format, assetPath, picture, isHighQualityPicture);
2631     string editData = "";
2632     string editDataCameraPath = GetEditDataCameraPath(assetPath);
2633     if (ReadEditdataFromFile(editDataCameraPath, editData) == E_OK &&
2634         GetPicture(fileId, picture, false, photoId, isHighQualityPicture) == E_OK) {
2635         MediaFileUtils::CopyFileUtil(assetPath, GetEditDataSourcePath(assetPath));
2636         int32_t ret = MediaChangeEffect::TakeEffectForPicture(picture, editData);
2637         FileUtils::DealPicture(format, assetPath, picture, isHighQualityPicture);
2638     }
2639     if (isHighQualityPicture) {
2640         RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2641         predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
2642         ValuesBucket values;
2643         values.Put(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
2644         values.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
2645         int32_t updatedRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
2646         if (updatedRows < 0) {
2647             MEDIA_ERR_LOG("update photo quality fail.");
2648         }
2649     }
2650 
2651     auto pictureManagerThread = PictureManagerThread::GetInstance();
2652     if (pictureManagerThread != nullptr) {
2653         pictureManagerThread->FinishAccessingPicture(photoId);
2654         pictureManagerThread->DeleteDataWithImageId(lastPhotoId_, LOW_QUALITY_PICTURE);
2655     }
2656     lastPhotoId_ = photoId;
2657     // 删除已经存在的异常后缀的图片
2658     size_t size = -1;
2659     MediaFileUtils::GetFileSize(oldFilePath, size);
2660     if (updateResult == E_OK && oldFilePath != "" && size > 0) {
2661         DeleteAbnormalFile(assetPath, fileId, oldFilePath);
2662     }
2663     return E_OK;
2664 }
2665 
AddFiltersExecute(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,const string & cachePath)2666 int32_t MediaLibraryPhotoOperations::AddFiltersExecute(MediaLibraryCommand& cmd,
2667     const shared_ptr<FileAsset>& fileAsset, const string& cachePath)
2668 {
2669     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
2670     int32_t fileId = fileAsset->GetId();
2671     string assetPath = fileAsset->GetFilePath();
2672     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2673     string editDataDirPath = GetEditDataDirPath(assetPath);
2674     CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Can not get editdara dir path");
2675     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
2676         "Can not create dir %{private}s", editDataDirPath.c_str());
2677     string sourcePath = GetEditDataSourcePath(assetPath);
2678     CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Can not get edit source path");
2679 
2680     if (cachePath.empty()) {
2681         // Photo目录照片复制到.editdata目录的source.jpg
2682         MediaFileUtils::CopyFileUtil(assetPath, sourcePath);
2683     } else {
2684         // cache移动到source.jpg
2685         int32_t subtype = fileAsset->GetPhotoSubType();
2686         MoveCacheFile(cmd, subtype, cachePath, sourcePath);
2687     }
2688 
2689     // 保存editdata_camera文件
2690     string editData;
2691     SaveEditDataCamera(cmd, assetPath, editData);
2692     // 生成水印
2693     int32_t ret = AddFiltersToPhoto(sourcePath, assetPath, editData);
2694     if (ret == E_OK) {
2695         MediaLibraryObjectUtils::ScanFileAsync(assetPath, to_string(fileAsset->GetId()), MediaLibraryApi::API_10);
2696     }
2697     std::shared_ptr<Media::Picture> picture;
2698     std::string photoId;
2699     bool isHighQualityPicture = false;
2700     if (GetPicture(fileId, picture, true, photoId, isHighQualityPicture) == E_OK) {
2701         return E_OK;
2702     }
2703     return ret;
2704 }
2705 
AddFiltersForCloudEnhancementPhoto(int32_t fileId,const string & assetPath,const string & editDataCameraSourcePath,const string & mimeType)2706 int32_t MediaLibraryPhotoOperations::AddFiltersForCloudEnhancementPhoto(int32_t fileId,
2707     const string& assetPath, const string& editDataCameraSourcePath, const string& mimeType)
2708 {
2709     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2710     string editDataDirPath = GetEditDataDirPath(assetPath);
2711     CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Can not get editdata dir path");
2712     string sourcePath = GetEditDataSourcePath(assetPath);
2713     CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Can not get edit source path");
2714 
2715     // copy source.jpg
2716     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
2717         "Can not create dir %{private}s, errno:%{public}d", editDataDirPath.c_str(), errno);
2718     bool copyResult = MediaFileUtils::CopyFileUtil(assetPath, sourcePath);
2719     if (!copyResult) {
2720         MEDIA_ERR_LOG("copy to source.jpg failed. errno=%{public}d, path: %{public}s", errno, assetPath.c_str());
2721     }
2722     string editData;
2723     MediaFileUtils::ReadStrFromFile(editDataCameraSourcePath, editData);
2724     ParseCloudEnhancementEditData(editData);
2725     string editDataCameraDestPath = PhotoFileUtils::GetEditDataCameraPath(assetPath);
2726     copyResult = MediaFileUtils::CopyFileUtil(editDataCameraSourcePath, editDataCameraDestPath);
2727     if (!copyResult) {
2728         MEDIA_ERR_LOG("copy editDataCamera failed. errno=%{public}d, path: %{public}s", errno,
2729             editDataCameraSourcePath.c_str());
2730     }
2731     // normal
2732     return AddFiltersToPhoto(sourcePath, assetPath, editData);
2733 }
2734 
SubmitEditCacheExecute(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,const string & cachePath)2735 int32_t MediaLibraryPhotoOperations::SubmitEditCacheExecute(MediaLibraryCommand& cmd,
2736     const shared_ptr<FileAsset>& fileAsset, const string& cachePath)
2737 {
2738     string editData;
2739     int32_t id = fileAsset->GetId();
2740     int32_t errCode = ParseMediaAssetEditData(cmd, editData);
2741     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to parse MediaAssetEditData");
2742     errCode = SaveSourceAndEditData(fileAsset, editData);
2743     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to save source and editData");
2744 
2745     int32_t subtype = fileAsset->GetPhotoSubType();
2746     if (subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2747         errCode = SubmitEditMovingPhotoExecute(cmd, fileAsset);
2748         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to SubmitEditMovingPhotoExecute");
2749     }
2750 
2751     string assetPath = fileAsset->GetFilePath();
2752     errCode = MoveCacheFile(cmd, subtype, cachePath, assetPath);
2753     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
2754         "Failed to move %{private}s to %{private}s, errCode: %{public}d",
2755         cachePath.c_str(), assetPath.c_str(), errCode);
2756 
2757     errCode = UpdateEditTime(id, MediaFileUtils::UTCTimeSeconds());
2758     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to update edit time, fileId:%{public}d", id);
2759     ResetOcrInfo(id);
2760     ScanFile(assetPath, false, true, true);
2761     MediaLibraryAnalysisAlbumOperations::UpdatePortraitAlbumCoverSatisfied(id);
2762     // delete cloud enhacement task
2763     vector<string> fileId;
2764     fileId.emplace_back(to_string(fileAsset->GetId()));
2765     vector<string> photoId;
2766     EnhancementManager::GetInstance().CancelTasksInternal(fileId, photoId, CloudEnhancementAvailableType::EDIT);
2767     if (!photoId.empty()) {
2768         CloudEnhancementGetCount::GetInstance().Report("EditCancellationType", photoId.front());
2769     }
2770     NotifyFormMap(id, assetPath, false);
2771     MediaLibraryVisionOperations::EditCommitOperation(cmd);
2772     return E_OK;
2773 }
2774 
SubmitCacheExecute(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,const string & cachePath)2775 int32_t MediaLibraryPhotoOperations::SubmitCacheExecute(MediaLibraryCommand& cmd,
2776     const shared_ptr<FileAsset>& fileAsset, const string& cachePath)
2777 {
2778     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
2779     int32_t subtype = fileAsset->GetPhotoSubType();
2780     CHECK_AND_RETURN_RET_LOG(CheckCacheCmd(cmd, subtype, fileAsset->GetDisplayName()),
2781         E_INVALID_VALUES, "Failed to check cache cmd");
2782     CHECK_AND_RETURN_RET_LOG(fileAsset->GetDateTrashed() == 0, E_IS_RECYCLED, "FileAsset is in recycle");
2783 
2784     int64_t pending = fileAsset->GetTimePending();
2785     CHECK_AND_RETURN_RET_LOG(
2786         pending == 0 || pending == UNCREATE_FILE_TIMEPENDING || pending == UNOPEN_FILE_COMPONENT_TIMEPENDING,
2787         E_IS_PENDING_ERROR, "FileAsset is in pending: %{public}ld", static_cast<long>(pending));
2788 
2789     string assetPath = fileAsset->GetFilePath();
2790     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2791 
2792     int32_t id = fileAsset->GetId();
2793     bool isEdit = (pending == 0);
2794 
2795     if (isEdit) {
2796         if (!PhotoEditingRecord::GetInstance()->StartCommitEdit(id)) {
2797             return E_IS_IN_REVERT;
2798         }
2799         int32_t errCode = SubmitEditCacheExecute(cmd, fileAsset, cachePath);
2800         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
2801         return errCode;
2802     } else if (IsCameraEditData(cmd)) {
2803         AddFiltersExecute(cmd, fileAsset, cachePath);
2804     } else {
2805         int32_t errCode = MoveCacheFile(cmd, subtype, cachePath, assetPath);
2806         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
2807             "Failed to move %{private}s to %{private}s, errCode: %{public}d",
2808             cachePath.c_str(), assetPath.c_str(), errCode);
2809     }
2810     ScanFile(assetPath, false, true, true);
2811     return E_OK;
2812 }
2813 
SaveSourceVideoFile(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,const string & assetPath)2814 int32_t MediaLibraryPhotoOperations::SaveSourceVideoFile(MediaLibraryCommand& cmd,
2815     const shared_ptr<FileAsset>& fileAsset, const string& assetPath)
2816 {
2817     MEDIA_INFO_LOG("Moving photo SaveSourceVideoFile begin, fileId:%{public}d", fileAsset->GetId());
2818     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
2819     string sourceImagePath = GetEditDataSourcePath(assetPath);
2820     CHECK_AND_RETURN_RET_LOG(!sourceImagePath.empty(), E_INVALID_PATH, "Can not get source image path");
2821     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
2822     CHECK_AND_RETURN_RET_LOG(!videoPath.empty(), E_INVALID_PATH, "Can not get video path");
2823     string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
2824     CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_PATH, "Can not get source video path");
2825     if (!MediaFileUtils::IsFileExists(sourceVideoPath)) {
2826         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(videoPath, sourceVideoPath) == E_SUCCESS,
2827             E_HAS_FS_ERROR, "Move video file failed, srcPath:%{private}s, newPath:%{private}s",
2828             videoPath.c_str(), sourceVideoPath.c_str());
2829     }
2830     return E_OK;
2831 }
2832 
SubmitEditMovingPhotoExecute(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)2833 int32_t MediaLibraryPhotoOperations::SubmitEditMovingPhotoExecute(MediaLibraryCommand& cmd,
2834     const shared_ptr<FileAsset>& fileAsset)
2835 {
2836     MEDIA_INFO_LOG("Moving photo SubmitEditMovingPhotoExecute begin, fileId:%{public}d", fileAsset->GetId());
2837     string assetPath = fileAsset->GetFilePath();
2838     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2839     int32_t errCode = E_OK;
2840     if (fileAsset->GetPhotoEditTime() == 0) { // the asset has not been edited before
2841         // Save video file in the photo direvtory to the .editdata directory
2842         errCode = SaveSourceVideoFile(cmd, fileAsset, assetPath);
2843         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
2844             "Failed to save %{private}s to sourcePath, errCode: %{public}d", assetPath.c_str(), errCode);
2845     }
2846 
2847     string cacheMovingPhotoVideoName;
2848     GetStringFromValuesBucket(cmd.GetValueBucket(), CACHE_MOVING_PHOTO_VIDEO_NAME, cacheMovingPhotoVideoName);
2849     if (cacheMovingPhotoVideoName.empty()) {
2850         string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
2851         CHECK_AND_RETURN_RET_LOG(!videoPath.empty(), E_INVALID_PATH, "Can not get video path");
2852         if (MediaFileUtils::IsFileExists(videoPath)) {
2853             MEDIA_INFO_LOG("Delete video file in photo directory, file is: %{private}s", videoPath.c_str());
2854             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteFile(videoPath), E_HAS_FS_ERROR,
2855                 "Failed to delete video file, path:%{private}s", videoPath.c_str());
2856         }
2857         errCode = UpdateMovingPhotoSubtype(fileAsset->GetId(), fileAsset->GetPhotoSubType());
2858         MEDIA_INFO_LOG("Moving photo graffiti editing, which becomes a normal photo, fileId:%{public}d",
2859             fileAsset->GetId());
2860     }
2861     return errCode;
2862 }
2863 
GetMovingPhotoCachePath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,string & imageCachePath,string & videoCachePath)2864 int32_t MediaLibraryPhotoOperations::GetMovingPhotoCachePath(MediaLibraryCommand& cmd,
2865     const shared_ptr<FileAsset>& fileAsset, string& imageCachePath, string& videoCachePath)
2866 {
2867     string imageCacheName;
2868     string videoCacheName;
2869     const ValuesBucket& values = cmd.GetValueBucket();
2870     GetStringFromValuesBucket(values, CACHE_FILE_NAME, imageCacheName);
2871     GetStringFromValuesBucket(values, CACHE_MOVING_PHOTO_VIDEO_NAME, videoCacheName);
2872     CHECK_AND_RETURN_RET_LOG(!imageCacheName.empty() || !videoCacheName.empty(),
2873         E_INVALID_VALUES, "Failed to check cache file of moving photo");
2874 
2875     string cacheDir = GetAssetCacheDir();
2876     if (!videoCacheName.empty()) {
2877         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoVideo(cacheDir + "/" + videoCacheName),
2878             E_INVALID_MOVING_PHOTO, "Failed to check cache video of moving photo");
2879     }
2880 
2881     string assetPath = fileAsset->GetPath();
2882     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_PATH, "Failed to get image path of moving photo");
2883     string assetVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
2884     CHECK_AND_RETURN_RET_LOG(!assetVideoPath.empty(), E_INVALID_PATH, "Failed to get video path of moving photo");
2885 
2886     if (imageCacheName.empty()) {
2887         imageCacheName = MediaFileUtils::GetTitleFromDisplayName(videoCacheName) + "_image." +
2888                          MediaFileUtils::GetExtensionFromPath(fileAsset->GetDisplayName());
2889         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(assetPath, cacheDir + "/" + imageCacheName),
2890             E_HAS_FS_ERROR, "Failed to copy image to cache");
2891     }
2892     if (videoCacheName.empty()) {
2893         videoCacheName = MediaFileUtils::GetTitleFromDisplayName(imageCacheName) + "_video.mp4";
2894         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(assetVideoPath, cacheDir + "/" + videoCacheName),
2895             E_HAS_FS_ERROR, "Failed to copy video to cache");
2896     }
2897 
2898     imageCachePath = cacheDir + "/" + imageCacheName;
2899     videoCachePath = cacheDir + "/" + videoCacheName;
2900     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(imageCachePath), E_NO_SUCH_FILE,
2901         "imageCachePath: %{private}s does not exist!", imageCachePath.c_str());
2902     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(videoCachePath), E_NO_SUCH_FILE,
2903         "videoCachePath: %{private}s does not exist!", videoCachePath.c_str());
2904     return E_OK;
2905 }
2906 
SubmitEffectModeExecute(MediaLibraryCommand & cmd)2907 int32_t MediaLibraryPhotoOperations::SubmitEffectModeExecute(MediaLibraryCommand& cmd)
2908 {
2909     int32_t id = -1;
2910     int32_t effectMode = -1;
2911     const ValuesBucket& values = cmd.GetValueBucket();
2912     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id) && id > 0,
2913         E_INVALID_VALUES, "Failed to get file id");
2914     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode) &&
2915         MediaFileUtils::CheckMovingPhotoEffectMode(effectMode), E_INVALID_VALUES,
2916         "Failed to check effect mode: %{public}d", effectMode);
2917     vector<string> columns = { PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME, PhotoColumn::PHOTO_SUBTYPE,
2918         PhotoColumn::MEDIA_TIME_PENDING, PhotoColumn::MEDIA_DATE_TRASHED, PhotoColumn::PHOTO_EDIT_TIME,
2919         PhotoColumn::MOVING_PHOTO_EFFECT_MODE };
2920     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(id),
2921         OperationObject::FILESYSTEM_PHOTO, columns);
2922     int32_t errCode = CheckFileAssetStatus(fileAsset, true);
2923     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to check status of fileAsset, id: %{public}d", id);
2924 
2925     string imageCachePath;
2926     string videoCachePath;
2927     errCode = GetMovingPhotoCachePath(cmd, fileAsset, imageCachePath, videoCachePath);
2928     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to get cache file path of moving photo");
2929 
2930     string assetPath = fileAsset->GetPath();
2931     string assetVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
2932     if (fileAsset->GetPhotoEditTime() == 0) { // save source moving photo
2933         string editDataDirPath = GetEditDataDirPath(assetPath);
2934         CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Failed to get edit dir path");
2935         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
2936             "Failed to create dir %{private}s", editDataDirPath.c_str());
2937 
2938         string sourceImagePath = GetEditDataSourcePath(assetPath);
2939         CHECK_AND_RETURN_RET_LOG(!sourceImagePath.empty(), E_INVALID_PATH, "Cannot get source image path");
2940         string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
2941         CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_PATH, "Cannot get source video path");
2942         if (!MediaFileUtils::IsFileExists(sourceVideoPath)) {
2943             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetVideoPath, sourceVideoPath) == E_SUCCESS,
2944                 E_HAS_FS_ERROR, "Move file failed, srcPath:%{private}s, newPath:%{private}s", assetVideoPath.c_str(),
2945                 sourceVideoPath.c_str());
2946         }
2947         if (!MediaFileUtils::IsFileExists(sourceImagePath)) {
2948             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetPath, sourceImagePath) == E_SUCCESS,
2949                 E_HAS_FS_ERROR, "Move file failed, srcPath:%{private}s, newPath:%{private}s", assetPath.c_str(),
2950                 sourceImagePath.c_str());
2951         }
2952     }
2953 
2954     CHECK_AND_RETURN_RET_LOG(Move(imageCachePath, assetPath) == E_OK, E_HAS_FS_ERROR, "Failed to move image");
2955     CHECK_AND_RETURN_RET_LOG(Move(videoCachePath, assetVideoPath) == E_OK, E_HAS_FS_ERROR, "Failed to move video");
2956     CHECK_AND_RETURN_RET_LOG(UpdateEffectMode(id, effectMode) == E_OK, errCode, "Failed to update effect mode");
2957     ScanFile(assetPath, true, true, true);
2958     return E_OK;
2959 }
2960 
SubmitCache(MediaLibraryCommand & cmd)2961 int32_t MediaLibraryPhotoOperations::SubmitCache(MediaLibraryCommand& cmd)
2962 {
2963     MediaLibraryTracer tracer;
2964     tracer.Start("MediaLibraryPhotoOperations::SubmitCache");
2965 
2966     if (IsSetEffectMode(cmd)) {
2967         return SubmitEffectModeExecute(cmd);
2968     }
2969 
2970     const ValuesBucket& values = cmd.GetValueBucket();
2971     string fileName;
2972     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, CACHE_FILE_NAME, fileName),
2973         E_INVALID_VALUES, "Failed to get fileName");
2974     string cacheDir = GetAssetCacheDir();
2975     string cachePath = cacheDir + "/" + fileName;
2976     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(cachePath), E_NO_SUCH_FILE,
2977         "cachePath: %{private}s does not exist!", cachePath.c_str());
2978     string movingPhotoVideoName;
2979     if (GetStringFromValuesBucket(values, CACHE_MOVING_PHOTO_VIDEO_NAME, movingPhotoVideoName)) {
2980         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(cacheDir + "/" + movingPhotoVideoName),
2981             E_NO_SUCH_FILE, "cahce moving video path: %{private}s does not exist!", cachePath.c_str());
2982     }
2983 
2984     int32_t id = 0;
2985     if (!GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id)) {
2986         string displayName;
2987         CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, PhotoColumn::MEDIA_NAME, displayName),
2988             E_INVALID_VALUES, "Failed to get displayName");
2989         CHECK_AND_RETURN_RET_LOG(
2990             MediaFileUtils::GetExtensionFromPath(displayName) == MediaFileUtils::GetExtensionFromPath(fileName),
2991             E_INVALID_VALUES, "displayName mismatches extension of cache file name");
2992         ValuesBucket reservedValues = values;
2993         id = CreateV10(cmd);
2994         CHECK_AND_RETURN_RET_LOG(id > 0, E_FAIL, "Failed to create asset");
2995         cmd.SetValueBucket(reservedValues);
2996     }
2997 
2998     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME,
2999         PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::MEDIA_TIME_PENDING, PhotoColumn::MEDIA_DATE_TRASHED,
3000         PhotoColumn::PHOTO_EDIT_TIME };
3001     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(
3002         PhotoColumn::MEDIA_ID, to_string(id), OperationObject::FILESYSTEM_PHOTO, columns);
3003     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES,
3004         "Failed to getmapmanagerthread:: FileAsset, fileId=%{public}d", id);
3005     int32_t errCode = SubmitCacheExecute(cmd, fileAsset, cachePath);
3006     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to submit cache, fileId=%{public}d", id);
3007     return id;
3008 }
3009 
ProcessMultistagesPhoto(bool isEdited,const std::string & path,const uint8_t * addr,const long bytes,int32_t fileId)3010 int32_t MediaLibraryPhotoOperations::ProcessMultistagesPhoto(bool isEdited, const std::string &path,
3011     const uint8_t *addr, const long bytes, int32_t fileId)
3012 {
3013     MediaLibraryTracer tracer;
3014     tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto");
3015     string editDataSourcePath = GetEditDataSourcePath(path);
3016     string editDataCameraPath = GetEditDataCameraPath(path);
3017 
3018     if (isEdited) {
3019         // 图片编辑过了只替换低质量裸图
3020         return FileUtils::SaveImage(editDataSourcePath, (void*)addr, bytes);
3021     } else {
3022         if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
3023             // 图片没编辑过且没有editdata_camera,只落盘在Photo目录
3024             return FileUtils::SaveImage(path, (void*)addr, bytes);
3025         } else {
3026             // 图片没编辑过且有editdata_camera
3027             MediaLibraryTracer tracer;
3028             tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto AddFiltersToPhoto");
3029             // (1) 先替换低质量裸图
3030             int ret = FileUtils::SaveImage(editDataSourcePath, (void*)addr, bytes);
3031             if (ret != E_OK) {
3032                 return ret;
3033             }
3034             // (2) 生成高质量水印滤镜图片
3035             string editData;
3036             CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
3037                 "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
3038             const string HIGH_QUALITY_PHOTO_STATUS = "high";
3039             CHECK_AND_RETURN_RET_LOG(
3040                 AddFiltersToPhoto(editDataSourcePath, path, editData, HIGH_QUALITY_PHOTO_STATUS) == E_OK,
3041                 E_FAIL, "Failed to add filters to photo");
3042             MediaLibraryObjectUtils::ScanFileAsync(path, to_string(fileId), MediaLibraryApi::API_10);
3043             return E_OK;
3044         }
3045     }
3046 }
3047 
ProcessMultistagesPhotoForPicture(bool isEdited,const std::string & path,std::shared_ptr<Media::Picture> & picture,int32_t fileId,const std::string & mime_type)3048 int32_t MediaLibraryPhotoOperations::ProcessMultistagesPhotoForPicture(bool isEdited, const std::string &path,
3049     std::shared_ptr<Media::Picture> &picture, int32_t fileId, const std::string &mime_type)
3050 {
3051     MediaLibraryTracer tracer;
3052     tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto");
3053     string editDataSourcePath = GetEditDataSourcePath(path);
3054     string editDataCameraPath = GetEditDataCameraPath(path);
3055 
3056     if (isEdited) {
3057         // 图片编辑过了只替换低质量裸图
3058         return FileUtils::SavePicture(editDataSourcePath, picture, mime_type, true);
3059     } else {
3060         if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
3061             // 图片没编辑过且没有editdata_camera,只落盘在Photo目录
3062             return FileUtils::SavePicture(path, picture, mime_type, true);
3063         } else {
3064             // 图片没编辑过且有editdata_camera
3065             MediaLibraryTracer tracer;
3066             tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto AddFiltersToPhoto");
3067             // (1) 先替换低质量裸图
3068             int ret = FileUtils::SavePicture(editDataSourcePath, picture, mime_type, true);
3069             if (ret != E_OK) {
3070                 return ret;
3071             }
3072             // (2) 生成高质量水印滤镜图片
3073             string editData;
3074             CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
3075                 "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
3076             CHECK_AND_RETURN_RET_LOG(AddFiltersToPicture(picture, path, editData, mime_type, true) == E_OK, E_FAIL,
3077                 "Failed to add filters to photo");
3078             return E_OK;
3079         }
3080     }
3081 }
3082 
AddFiltersToPhoto(const std::string & inputPath,const std::string & outputPath,const std::string & editdata,const std::string & photoStatus)3083 int32_t MediaLibraryPhotoOperations::AddFiltersToPhoto(const std::string &inputPath,
3084     const std::string &outputPath, const std::string &editdata, const std::string &photoStatus)
3085 {
3086     MEDIA_INFO_LOG("AddFiltersToPhoto inputPath: %{public}s, outputPath: %{public}s, editdata: %{public}s",
3087         inputPath.c_str(), outputPath.c_str(), editdata.c_str());
3088     std::string info = editdata;
3089     size_t lastSlash = outputPath.rfind('/');
3090     CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && outputPath.size() > (lastSlash + 1), E_INVALID_VALUES,
3091         "Failed to check outputPath: %{public}s", outputPath.c_str());
3092     string tempOutputPath = outputPath.substr(0, lastSlash) +
3093         "/filters_" + photoStatus + outputPath.substr(lastSlash + 1);
3094     int32_t ret = MediaFileUtils::CreateAsset(tempOutputPath);
3095     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS || ret == E_FILE_EXIST, E_HAS_FS_ERROR,
3096         "Failed to create temp filters file %{private}s", tempOutputPath.c_str());
3097     ret = MediaChangeEffect::TakeEffect(inputPath, tempOutputPath, info);
3098     if (ret != E_OK) {
3099         MEDIA_ERR_LOG("MediaLibraryPhotoOperations: AddFiltersToPhoto: TakeEffect error. ret = %d", ret);
3100         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
3101             "Failed to delete temp filters file, errno: %{public}d", errno);
3102         return E_ERR;
3103     }
3104 
3105     string editDataPath = GetEditDataPath(outputPath);
3106     if (MediaFileUtils::IsFileExists(editDataPath)) {
3107         MEDIA_INFO_LOG("Editdata path: %{private}s exists, cannot add filters to photo", editDataPath.c_str());
3108         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
3109             "Failed to delete temp filters file, errno: %{public}d", errno);
3110         return E_OK;
3111     }
3112 
3113     ret = rename(tempOutputPath.c_str(), outputPath.c_str());
3114     if (ret < 0) {
3115         MEDIA_ERR_LOG("Failed to rename temp filters file, ret: %{public}d, errno: %{public}d", ret, errno);
3116         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
3117             "Failed to delete temp filters file, errno: %{public}d", errno);
3118         return ret;
3119     }
3120     MEDIA_INFO_LOG("AddFiltersToPhoto finish");
3121     return E_OK;
3122 }
3123 
AddFiltersToPicture(std::shared_ptr<Media::Picture> & inPicture,const std::string & outputPath,string & editdata,const std::string & mime_type,bool isHighQualityPicture)3124 int32_t MediaLibraryPhotoOperations::AddFiltersToPicture(std::shared_ptr<Media::Picture> &inPicture,
3125     const std::string &outputPath, string &editdata, const std::string &mime_type, bool isHighQualityPicture)
3126 {
3127     if (inPicture == nullptr) {
3128         MEDIA_ERR_LOG("AddFiltersToPicture: picture is null");
3129         return E_ERR;
3130     }
3131     MEDIA_INFO_LOG("AddFiltersToPicture outputPath: %{public}s, editdata: %{public}s",
3132         outputPath.c_str(), editdata.c_str());
3133     size_t lastSlash = outputPath.rfind('/');
3134     CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && outputPath.size() > (lastSlash + 1), E_INVALID_VALUES,
3135         "Failed to check outputPath: %{public}s", outputPath.c_str());
3136     int32_t ret = MediaChangeEffect::TakeEffectForPicture(inPicture, editdata);
3137     FileUtils::DealPicture(mime_type, outputPath, inPicture, isHighQualityPicture);
3138     return E_OK;
3139 }
3140 
ProcessMultistagesVideo(bool isEdited,const std::string & path)3141 int32_t MediaLibraryPhotoOperations::ProcessMultistagesVideo(bool isEdited, const std::string &path)
3142 {
3143     MEDIA_INFO_LOG("ProcessMultistagesVideo path: %{public}s, isEdited: %{public}d", path.c_str(), isEdited);
3144     return FileUtils::SaveVideo(path, isEdited);
3145 }
3146 
RemoveTempVideo(const std::string & path)3147 int32_t MediaLibraryPhotoOperations::RemoveTempVideo(const std::string &path)
3148 {
3149     MEDIA_INFO_LOG("RemoveTempVideo path: %{public}s", path.c_str());
3150     return FileUtils::DeleteTempVideoFile(path);
3151 }
3152 
PhotoEditingRecord()3153 PhotoEditingRecord::PhotoEditingRecord()
3154 {
3155 }
3156 
GetInstance()3157 shared_ptr<PhotoEditingRecord> PhotoEditingRecord::GetInstance()
3158 {
3159     if (instance_ == nullptr) {
3160         lock_guard<mutex> lock(mutex_);
3161         if (instance_ == nullptr) {
3162             instance_ = make_shared<PhotoEditingRecord>();
3163         }
3164     }
3165     return instance_;
3166 }
3167 
StartCommitEdit(int32_t fileId)3168 bool PhotoEditingRecord::StartCommitEdit(int32_t fileId)
3169 {
3170     unique_lock<shared_mutex> lock(addMutex_);
3171     if (revertingPhotoSet_.count(fileId) > 0) {
3172         MEDIA_ERR_LOG("Photo %{public}d is reverting", fileId);
3173         return false;
3174     }
3175     editingPhotoSet_.insert(fileId);
3176     return true;
3177 }
3178 
EndCommitEdit(int32_t fileId)3179 void PhotoEditingRecord::EndCommitEdit(int32_t fileId)
3180 {
3181     unique_lock<shared_mutex> lock(addMutex_);
3182     editingPhotoSet_.erase(fileId);
3183 }
3184 
StartRevert(int32_t fileId)3185 bool PhotoEditingRecord::StartRevert(int32_t fileId)
3186 {
3187     unique_lock<shared_mutex> lock(addMutex_);
3188     if (editingPhotoSet_.count(fileId) > 0) {
3189         MEDIA_ERR_LOG("Photo %{public}d is committing edit", fileId);
3190         return false;
3191     }
3192     revertingPhotoSet_.insert(fileId);
3193     return true;
3194 }
3195 
EndRevert(int32_t fileId)3196 void PhotoEditingRecord::EndRevert(int32_t fileId)
3197 {
3198     unique_lock<shared_mutex> lock(addMutex_);
3199     revertingPhotoSet_.erase(fileId);
3200 }
3201 
IsInRevertOperation(int32_t fileId)3202 bool PhotoEditingRecord::IsInRevertOperation(int32_t fileId)
3203 {
3204     shared_lock<shared_mutex> lock(addMutex_);
3205     return revertingPhotoSet_.count(fileId) > 0;
3206 }
3207 
IsInEditOperation(int32_t fileId)3208 bool PhotoEditingRecord::IsInEditOperation(int32_t fileId)
3209 {
3210     shared_lock<shared_mutex> lock(addMutex_);
3211     if (editingPhotoSet_.count(fileId) > 0 || revertingPhotoSet_.count(fileId) > 0) {
3212         return true;
3213     }
3214     return false;
3215 }
3216 
ConvertPhotoPathToThumbnailDirPath(std::string & path)3217 static bool ConvertPhotoPathToThumbnailDirPath(std::string& path)
3218 {
3219     const std::string photoRelativePath = "/Photo/";
3220     const std::string thumbRelativePath = "/.thumbs/Photo/";
3221     size_t pos = path.find(photoRelativePath);
3222     if (pos == string::npos) {
3223         MEDIA_ERR_LOG("source file invalid! path is %{public}s", path.c_str());
3224         return false;
3225     }
3226     path.replace(pos, photoRelativePath.length(), thumbRelativePath);
3227     return true;
3228 }
3229 
StoreThumbnailSize(const string & photoId,const string & photoPath)3230 void MediaLibraryPhotoOperations::StoreThumbnailSize(const string& photoId, const string& photoPath)
3231 {
3232     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3233     if (rdbStore == nullptr) {
3234         MEDIA_ERR_LOG("Medialibrary rdbStore is nullptr!");
3235         return;
3236     }
3237 
3238     string thumbnailDir {photoPath};
3239     if (!ConvertPhotoPathToThumbnailDirPath(thumbnailDir)) {
3240         MEDIA_ERR_LOG("Failed to get thumbnail dir path from photo path! file id: %{public}s", photoId.c_str());
3241         return;
3242     };
3243     uint64_t photoThumbnailSize = GetFolderSize(thumbnailDir);
3244     string sql = "INSERT OR REPLACE INTO " + PhotoExtColumn::PHOTOS_EXT_TABLE + " (" +
3245         PhotoExtColumn::PHOTO_ID + ", " + PhotoExtColumn::THUMBNAIL_SIZE +
3246         ") VALUES (" + photoId + ", " + to_string(photoThumbnailSize) + ")";
3247     int32_t ret = rdbStore->ExecuteSql(sql);
3248     if (ret != NativeRdb::E_OK) {
3249         MEDIA_ERR_LOG("Failed to execute sql, photoId is %{public}s, error code is %{public}d", photoId.c_str(), ret);
3250         return;
3251     }
3252 }
3253 
HasDroppedThumbnailSize(const string & photoId)3254 bool MediaLibraryPhotoOperations::HasDroppedThumbnailSize(const string& photoId)
3255 {
3256     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3257     if (rdbStore == nullptr) {
3258         MEDIA_ERR_LOG("Medialibrary rdbStore is nullptr!");
3259         return false;
3260     }
3261 
3262     string sql = "DELETE FROM " + PhotoExtColumn::PHOTOS_EXT_TABLE +
3263         " WHERE " + PhotoExtColumn::PHOTO_ID + " = " + photoId + ";";
3264     int32_t ret = rdbStore->ExecuteSql(sql);
3265     if (ret != NativeRdb::E_OK) {
3266         MEDIA_ERR_LOG("Failed to execute sql, photoId is %{public}s, error code is %{public}d", photoId.c_str(), ret);
3267         return false;
3268     }
3269     return true;
3270 }
3271 
ScanMovingPhoto(MediaLibraryCommand & cmd,const vector<string> & columns)3272 shared_ptr<NativeRdb::ResultSet> MediaLibraryPhotoOperations::ScanMovingPhoto(MediaLibraryCommand &cmd,
3273     const vector<string> &columns)
3274 {
3275     if (columns.empty()) {
3276         MEDIA_ERR_LOG("column is empty");
3277         return nullptr;
3278     }
3279     string uri = columns[0]; // 0 in columns predicates uri
3280     string path = MediaFileUri::GetPathFromUri(uri, true);
3281     string fileId = MediaFileUri::GetPhotoId(uri);
3282     MediaLibraryObjectUtils::ScanFileAsync(path, fileId, MediaLibraryApi::API_10);
3283     return nullptr;
3284 }
3285 
ScanFileWithoutAlbumUpdate(MediaLibraryCommand & cmd)3286 int32_t MediaLibraryPhotoOperations::ScanFileWithoutAlbumUpdate(MediaLibraryCommand &cmd)
3287 {
3288     if (!PermissionUtils::IsNativeSAApp()) {
3289         MEDIA_DEBUG_LOG("do not have permission");
3290         return E_VIOLATION_PARAMETERS;
3291     }
3292     const ValuesBucket &values = cmd.GetValueBucket();
3293     string uriString;
3294     if (!GetStringFromValuesBucket(values, MEDIA_DATA_DB_URI, uriString)) {
3295         return E_INVALID_VALUES;
3296     }
3297     string path = MediaFileUri::GetPathFromUri(uriString, true);
3298     string fileIdStr = MediaFileUri::GetPhotoId(uriString);
3299     int32_t fileId = 0;
3300     if (MediaLibraryDataManagerUtils::IsNumber(fileIdStr)) {
3301         fileId = atoi(fileIdStr.c_str());
3302     }
3303     MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(path, false, false, true, fileId);
3304 
3305     return E_OK;
3306 }
3307 
UpdateDirty(int32_t fileId)3308 static void UpdateDirty(int32_t fileId)
3309 {
3310     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
3311     predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
3312     predicates.EqualTo(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
3313     predicates.EqualTo(PhotoColumn::PHOTO_IS_TEMP, 0);
3314     predicates.EqualTo(PhotoColumn::PHOTO_DIRTY, -1);
3315     ValuesBucket values;
3316     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_NEW));
3317     int32_t updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
3318     MEDIA_INFO_LOG("update dirty to 1, file_id:%{public}d, changedRows:%{public}d", fileId, updateDirtyRows);
3319 }
3320 
DegenerateMovingPhoto(MediaLibraryCommand & cmd)3321 int32_t MediaLibraryPhotoOperations::DegenerateMovingPhoto(MediaLibraryCommand &cmd)
3322 {
3323     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH,
3324         PhotoColumn::MEDIA_NAME, PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::PHOTO_EDIT_TIME };
3325     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
3326         OperationObject::FILESYSTEM_PHOTO, columns);
3327     if (fileAsset == nullptr) {
3328         MEDIA_ERR_LOG("failed to query fileAsset");
3329         return E_INVALID_VALUES;
3330     }
3331 
3332     if (fileAsset->GetPhotoSubType() != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
3333         MEDIA_INFO_LOG("fileAsset is not moving photo");
3334         return E_OK;
3335     }
3336 
3337     if (fileAsset->GetPhotoEditTime() > 0) {
3338         MEDIA_INFO_LOG("moving photo is edited");
3339         return E_OK;
3340     }
3341 
3342     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(fileAsset->GetFilePath());
3343     size_t videoSize = 0;
3344     if (MediaFileUtils::GetFileSize(videoPath, videoSize) && videoSize > 0) {
3345         MEDIA_INFO_LOG("no need to degenerate, video size:%{public}d", static_cast<int32_t>(videoSize));
3346         return E_OK;
3347     }
3348 
3349     if (MediaFileUtils::IsFileExists(videoPath)) {
3350         MEDIA_INFO_LOG("delete empty video file, size:%{public}d", static_cast<int32_t>(videoSize));
3351         (void)MediaFileUtils::DeleteFile(videoPath);
3352     }
3353 
3354     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3355     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore");
3356     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
3357     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
3358     ValuesBucket values;
3359     values.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
3360     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, predicates);
3361     if (updatedRows <= 0) {
3362         MEDIA_WARN_LOG("Failed to update subtype, updatedRows=%{public}d", updatedRows);
3363         return updatedRows;
3364     }
3365     UpdateDirty(fileAsset->GetId());
3366 
3367     string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetFilePath());
3368     auto watch = MediaLibraryNotify::GetInstance();
3369     watch->Notify(
3370         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri),
3371         NotifyType::NOTIFY_UPDATE);
3372     return updatedRows;
3373 }
3374 
UpdateOwnerAlbumId(MediaLibraryCommand & cmd)3375 int32_t MediaLibraryPhotoOperations::UpdateOwnerAlbumId(MediaLibraryCommand &cmd)
3376 {
3377     const ValuesBucket &values = cmd.GetValueBucket();
3378     int32_t targetAlbumId = 0;
3379     CHECK_AND_RETURN_RET(
3380         GetInt32FromValuesBucket(values, PhotoColumn::PHOTO_OWNER_ALBUM_ID, targetAlbumId), E_HAS_DB_ERROR);
3381 
3382     vector<string> columns = { PhotoColumn::PHOTO_OWNER_ALBUM_ID, PhotoColumn::MEDIA_ID };
3383     auto predicates = cmd.GetAbsRdbPredicates();
3384     auto resultSetQuery = MediaLibraryRdbStore::QueryWithFilter(*predicates, columns);
3385     if (resultSetQuery == nullptr) {
3386         MEDIA_ERR_LOG("album id is not exist");
3387         return E_INVALID_ARGUMENTS;
3388     }
3389     if (resultSetQuery->GoToFirstRow() != NativeRdb::E_OK) {
3390         return E_HAS_DB_ERROR;
3391     }
3392     int32_t originalAlbumId = GetInt32Val(PhotoColumn::PHOTO_OWNER_ALBUM_ID, resultSetQuery);
3393     resultSetQuery->Close();
3394 
3395     int32_t rowId = UpdateFileInDb(cmd);
3396     if (rowId < 0) {
3397         MEDIA_ERR_LOG("Update Photo In database failed, rowId=%{public}d", rowId);
3398         return rowId;
3399     }
3400 
3401     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(MediaLibraryUnistoreManager::GetInstance().GetRdbStore(),
3402         { to_string(PhotoAlbumSubType::IMAGE), to_string(PhotoAlbumSubType::VIDEO) });
3403     MediaLibraryRdbUtils::UpdateUserAlbumInternal(
3404         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(originalAlbumId) });
3405     MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
3406         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(originalAlbumId) });
3407     MediaLibraryRdbUtils::UpdateUserAlbumInternal(
3408         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(targetAlbumId) });
3409     MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
3410         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(targetAlbumId) });
3411 
3412     auto watch = MediaLibraryNotify::GetInstance();
3413     if (watch != nullptr) {
3414         watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(rowId),
3415             NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, originalAlbumId);
3416         watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(rowId),
3417             NotifyType::NOTIFY_ALBUM_ADD_ASSET, targetAlbumId);
3418     }
3419     return rowId;
3420 }
3421 } // namespace Media
3422 } // namespace OHOS
3423